I was reading about Action Delegate on MSDN and so this under syntax
public delegate void Action<in T>(T obj);
Than I looked in c-sharpcorner.com and it used this syntax
public delegate void Action<T>(T obj);
As you can see there is no in
before T.
Which syntax is right and what does that in
mean?
EDIT: The same syntax used for Predicate
.
Thanks.
in
and out
(generic contravariance and covariance) were only introduced in C# 4, and the delegates and interfaces were modified for .NET 4 - so Action<T>
in .NET 3.5 became Action<in T>
in .NET 4.
The article you're referring to is from 2006, well before .NET 4 came out.
If you change which version of MSDN you're displaying, you'll see the change - for example, the .NET 3.5 version shows it without the in
.
该in
部分是协方差和逆变 ,并介绍了在.NET 4.0中,你链接到被刊登在2006年之前,.NET 4.0的文章被释放(所以显然它并不是指合作[NTRA]方差)。
It may be worth noting that conceptually all delegate types could in theory be inherently covariant with any type parameter used only as the return type and contravariant with regard to type parameters used only for method parameters passed by value, and compilers could automatically allow for such variance, except for one problem: while the in
declaration of Action
will prevent the compiler from squawking if an Action<Animal>
is passed to a method that expects an Action<Cat>
, some methods that expect an Action<Cat>
may behave very badly if given an Action<Animal>
. In general, methods which should only accept delegates of types with covariance/contravariance specifiers if they will work correctly with all such delegates; otherwise they should accept delegate types without such specifiers.
Most methods which accept an Action<Cat>
will work just fine with an Action<Animal>
, so Microsoft decided retroactively to make Action<T>
contravariant. Because many methods which accept an EventHandler<T>
could fail very badly if given anything that didn't perfectly match the expected type, EventHandler<T>
was not made contravariant.
In retrospect, if each delegate type had defined its own Combine
method, it would have been possible to make delegate covariance and contravariance work in almost all cases. If CatEventArgs:AnimalEventArgs
, saying
EventHandler<CatEventArgs> myEvents=null;
void AddEvent(EventHandler<CatEventArgs> newEvent)
{
myEvents = EventHandler<CatEventArgs>.Combine(myEvents, newEvent);
}
could have turned a passed-in EventHandler<AnimalEventsArgs>
into an EventHandler<CatEventArgs>
, which could then be combined with any other delegate that could likewise be converted into an EventHandler<CatEventArgs>
. Unfortunately, since Combine
was only defined on Delegate
, there's no way by which the Combine
method can know what delegate type is needed by the calling code [IMHO, even without covariance/contravariance, it would have been nice to have delegates define their own Combine
and Remove
methods, since that would have avoided the need to typecast the result of Delegate.Combine
].
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.