我正在MSDN上阅读有关行动代表的内容,因此在语法
下阅读 public delegate void Action<in T>(T obj);
比我查看c-sharpcorner.com并使用了这种语法
public delegate void Action<T>(T obj);
正如您所见,T之前没有in
哪种语法是正确的,in
是什么意思?
编辑:与Predicate
使用的语法相同。
感谢。
答案 0 :(得分:10)
in
和out
(通用逆变和协方差)仅在C#4中引入,并且代理和接口已针对.NET 4进行了修改 - 因此.NET 3.5中的Action<T>
变为.NET 4中的Action<in T>
。
你所指的文章是从2006年开始的,远在.NET 4出版之前。
如果您更改了所显示的MSDN版本,则会看到更改 - 例如,.NET 3.5 version会在没有in
的情况下显示该更改。
答案 1 :(得分:9)
in
部分用于covariance and contravariance,并且是在.NET 4.0中引入的,您链接到的文章是在.NET 4.0发布之前于2006年发布的(所以很明显它没有引用合作[ NTRA]方差)。
答案 2 :(得分:1)
值得注意的是,从概念上讲,所有委托类型在理论上可以与任何类型参数本身协变,仅用作返回类型和逆变量,类型参数仅用于通过值传递的方法参数,编译器可以自动允许对于这样的差异,除了一个问题:in
Action
声明会阻止编译器在将Action<Animal>
传递给期望Action<Cat>
的方法时发出嘎嘎声,如果给定Action<Cat>
,期望Action<Animal>
的某些方法可能会表现得非常糟糕。一般而言,如果方法能够与所有这些代表一起正确地工作,那么这些方法应该只接受具有协方差/逆变规范的类型的代表;否则他们应该接受没有这些说明者的代表类型。
接受Action<Cat>
的大多数方法都可以正常使用Action<Animal>
,因此Microsoft决定追溯性地使Action<T>
逆变。因为许多接受EventHandler<T>
的方法如果给出与预期类型不完全匹配的任何东西,可能会非常糟糕地失败,EventHandler<T>
不是逆变的。
回想起来,如果每个代表类型都定义了自己的Combine
方法,那么几乎在所有情况下都可以使代表协方差和逆变成功。如果CatEventArgs:AnimalEventArgs
,请说
EventHandler<CatEventArgs> myEvents=null;
void AddEvent(EventHandler<CatEventArgs> newEvent)
{
myEvents = EventHandler<CatEventArgs>.Combine(myEvents, newEvent);
}
可以将传入的EventHandler<AnimalEventsArgs>
转换为EventHandler<CatEventArgs>
,然后可以将其与任何其他代理组合,这些代理同样可以转换为EventHandler<CatEventArgs>
。不幸的是,由于Combine
仅在Delegate
上定义,Combine
方法无法知道调用代码需要什么代理类型[恕我直言,即使没有协方差/逆变,如果让代理人定义他们自己的Combine
和Remove
方法会很好,因为那样就不需要对Delegate.Combine
]的结果进行类型转换。