![]() CATEGORIES: BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism |
Enough with the Delegate Definitions Already
(Generic Delegates) Many years ago, when the .NET Framework was just starting to be developed, Microsoft introduced the notion of delegates. As programmers were adding classes to the FCL, they would define new delegate types any place they introduced a callback method. Over time, many, many delegates got defined. In fact, in MSCorLib.dll alone, close to 50 delegate types are now defined. Let’s just look at a few of them.
public delegate void TryCode(Object userData); public delegate void WaitCallback(Object state); public delegate void TimerCallback(Object state); public delegate void ContextCallback(Object state); public delegate void SendOrPostCallback(Object state); public delegate void ParameterizedThreadStart(Object obj);
Do you notice anything similar about the few delegate definitions that I selected? They are really all the same: a variable of any of these delegate types must refer to a method that takes an Object and returns void. There is really no reason to have all of these delegate types defined; there really just needs to be one. In fact, now that the .NET Framework supports generics, we really just need a few generic del- egates (defined in the System namespace) that represent methods that take up to 16 arguments.
public delegate void Action(); // OK, this one is not generic public delegate void Action<T>(T obj); public delegate void Action<T1, T2>(T1 arg1, T2 arg2); public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3); ... public delegate void Action<T1, ..., T16>(T1 arg1, ..., T16 arg16);
So the .NET Framework now ships with 17 Action delegates that range from having no arguments to having 16 arguments. If you ever need to call a method that has more than 16 arguments, you will be forced to define your own delegate type, but this is very unlikely. In addition to the Action delegates, the .NET Framework ships with 17 Func delegates, which al- low the callback method to return a value.
public delegate TResult Func<TResult>(); public delegate TResult Func<T, TResult>(T arg); public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3); ... public delegate TResult Func<T1,..., T16, TResult>(T1 arg1, ..., T16 arg16);
It is now recommended that these delegate types be used wherever possible instead of developers defining even more delegate types in their code. This reduces the number of types in the system and also simplifies coding. However, you might have to define your own delegate if you need to pass an argument by reference using the ref or out keyword.
delegate void Bar(ref Int32 z);
You may also have to do this if you want your delegate to take a variable number of arguments via C#’s params keyword, if you want to specify any default values for any of your delegate’s arguments, or if you need to constrain a delegate’s generic type argument. When using delegates that take generic arguments and return values, contra-variance and co- variance come into play, and it is recommended that you always take advantage of these features because they have no ill effects and enable your delegates to be used in more scenarios. For more information about this, see the “Delegate and Interface Contra-variant and Covariant Generic Type Arguments” section in Chapter 12, “Generics.”
Date: 2016-03-03; view: 912
|