Action <t>或Action <in t =“”>?</in> </t>

时间:2010-11-02 06:59:22

标签: c# .net generics delegates

我正在MSDN上阅读有关行动代表的内容,因此在语法

下阅读
 public delegate void Action<in T>(T obj);

比我查看c-sharpcorner.com并使用了这种语法

public delegate void Action<T>(T obj);   

正如您所见,T之前没有in 哪种语法是正确的,in是什么意思? 编辑:与Predicate使用的语法相同。

感谢。

3 个答案:

答案 0 :(得分:10)

inout(通用逆变和协方差)仅在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方法无法知道调用代码需要什么代理类型[恕我直言,即使没有协方差/逆变,如果让代理人定义他们自己的CombineRemove方法会很好,因为那样就不需要对Delegate.Combine]的结果进行类型转换。