I understand HOW to use delegates, but in what situations would you actually use them? The examples I see in the literature are all in situations where the code could just be written without ever using them.
Delegates are extremely useful in multithreading and cross-thread operations. If you try accessing a Button control on a Windows Form created on Thread 1 by Thread 2, you'll get a nice yellow error telling you "This button cannot be accessed from a thread other than which it was created on." In that case, you would use delegates to play with the button.
There are seriously too many usefull situations to apply the usage of delegates to go and list them off -
I would say these are at the top of the usefulness list:
Creating a custom scope - so lets say you want to apply a method/action to a list of objects and apply locally scoped values into the body of the delegate but really don't need to add a bunch of additional variables to the scope of the entire class...
[code] [STAThread] public static void Main() { // Creating a custom window... var win = new Form(); // opening an xml file... var doc = new XmlDocument(); doc.Load("C:\MyDoc.xml"); var root = doc.DocumentElement;
//Cycling through each of the nodes in the root element of the XML file foreach (var child in root.ChildNodes.Cast()) { // Creating a reference to the node var node = child; var name = node.GetAttribute("name"); // Creating a new button var button = new Button() { Dock = DockStyle.Top, Text = name };
// Giving the button's click handler a delegate that has access to // the node that is associated with this itteration of the foreach // loop. This would be difficult using an externally defined method button.Click += delegate { var message = node.GetAttribute("message"); MessageBox.Show("The node named " + name + " had the message: " + message); //Obviously you won't often be creating buttons like this - but you could very //easily add actions to the Tags of a tree node or a custom class of your own. };
// adding the button to the form win.Controls.Add(button); }
// showing the completed dynamic window win.ShowDialog(); }
} [/code]
also - when used properly - delegates can make huge reductions in your code. Take for example this generic filter...
[code] public class GenericObjectFilter { public TItem[] FilterObjects(TItem[] items, Func identifier, string[] include) { var results = new List(); foreach (var item in items) if (include.Contains(identifier(item))) results.Add(item); return results.ToArray(); } }
[/code]
This one filter can be used to filter literally any object in existence...
[code] public class SomeClassA { public string ClassAName { get; set; } } public class SomeClassB { public string ClassBName { get; set; } } public class SomeClassC { public string ClassCName { get; set; } }
static class Program { [STAThread] public static void Main() { var filterStrings = new[] {"Aardvark", "Video", "Game"};
var collectionA = new SomeClassA[100]; var collectionB = new SomeClassB[100]; var collectionC = new SomeClassC[100];
var filter = new GenericObjectFilter();
var filteredA = filter.FilterObjects( collectionA, item => item.ClassAName, filterStrings);
var filteredB = filter.FilterObjects( collectionB, item => item.ClassBName, filterStrings);
var filteredC = filter.FilterObjects( collectionC, item => item.ClassCName, filterStrings);
// You now have filtered collections of 3 totally different object type collections // and you only ever wrote one single filter. }
}
[/code]
So let's say the filter you wrote was like 200 lines of code long... and you had to access three differing parts of the object you are filtering - without a delegate to tell the filter method how to grab the information it needs, you would actually have to write 3 different copies of the same exact filter - or 100 different copies if you had 100 different item types to filter.
but this way you can stick this filter in a DLL somewhere along with a bunch of other usefull stuff and just use it whenever you need it.
anyways - that's just a couple of uses - Once you start using them I garauntee you will find hundreds of uses for them.
Comments
I would say these are at the top of the usefulness list:
Creating a custom scope - so lets say you want to apply a method/action to a list of objects and apply locally scoped values into the body of the delegate but really don't need to add a bunch of additional variables to the scope of the entire class...
[code]
[STAThread]
public static void Main()
{
// Creating a custom window...
var win = new Form();
// opening an xml file...
var doc = new XmlDocument();
doc.Load("C:\MyDoc.xml");
var root = doc.DocumentElement;
//Cycling through each of the nodes in the root element of the XML file
foreach (var child in root.ChildNodes.Cast())
{
// Creating a reference to the node
var node = child;
var name = node.GetAttribute("name");
// Creating a new button
var button = new Button()
{
Dock = DockStyle.Top,
Text = name
};
// Giving the button's click handler a delegate that has access to
// the node that is associated with this itteration of the foreach
// loop. This would be difficult using an externally defined method
button.Click +=
delegate
{
var message = node.GetAttribute("message");
MessageBox.Show("The node named " + name + " had the message:
" + message);
//Obviously you won't often be creating buttons like this - but you could very
//easily add actions to the Tags of a tree node or a custom class of your own.
};
// adding the button to the form
win.Controls.Add(button);
}
// showing the completed dynamic window
win.ShowDialog();
}
}
[/code]
also - when used properly - delegates can make huge reductions in your code. Take for example this generic filter...
[code]
public class GenericObjectFilter
{
public TItem[] FilterObjects(TItem[] items, Func identifier, string[] include)
{
var results = new List();
foreach (var item in items)
if (include.Contains(identifier(item)))
results.Add(item);
return results.ToArray();
}
}
[/code]
This one filter can be used to filter literally any object in existence...
[code]
public class SomeClassA
{
public string ClassAName { get; set; }
}
public class SomeClassB
{
public string ClassBName { get; set; }
}
public class SomeClassC
{
public string ClassCName { get; set; }
}
static class Program
{
[STAThread]
public static void Main()
{
var filterStrings = new[] {"Aardvark", "Video", "Game"};
var collectionA = new SomeClassA[100];
var collectionB = new SomeClassB[100];
var collectionC = new SomeClassC[100];
var filter = new GenericObjectFilter();
var filteredA = filter.FilterObjects(
collectionA,
item => item.ClassAName,
filterStrings);
var filteredB = filter.FilterObjects(
collectionB,
item => item.ClassBName,
filterStrings);
var filteredC = filter.FilterObjects(
collectionC,
item => item.ClassCName,
filterStrings);
// You now have filtered collections of 3 totally different object type collections
// and you only ever wrote one single filter.
}
}
[/code]
So let's say the filter you wrote was like 200 lines of code long... and you had to access three differing parts of the object you are filtering - without a delegate to tell the filter method how to grab the information it needs, you would actually have to write 3 different copies of the same exact filter - or 100 different copies if you had 100 different item types to filter.
but this way you can stick this filter in a DLL somewhere along with a bunch of other usefull stuff and just use it whenever you need it.
anyways - that's just a couple of uses - Once you start using them I garauntee you will find hundreds of uses for them.
><//~Psightoplasm`~
Regards
Simon
Do you have anything more to read on .NET?[/color]