我对以下方法调用有疑问:
var ctl1 = this.FindControlRecursively("SomeField") as HiddenField;
var ctl = this.FindControlRecursively<HiddenField>("SomeField");
以下是这两个电话的IL:
IL_0010: ldstr "AsyncReset"
IL_0015: call class [System.Web]System.Web.UI.Control [Amc.WebG081.MethodExtensions]Amc.WebG081.ControlExtensions::FindControlRecursively(class [System.Web]System.Web.UI.Control,string)
IL_001a: isinst [System.Web]System.Web.UI.WebControls.HiddenField
IL_001f: stloc.0
IL_0020: ldarg.0
IL_0021: ldstr "AsyncReset"
IL_0026: call !!0 [Amc.WebG081.MethodExtensions]Amc.WebG081.ControlExtensions::FindControlRecursively<class [System.Web]System.Web.UI.WebControls.HiddenField>(class [System.Web]System.Web.UI.Control,string)
我一直认为在这种情况下,这种方法的通用版本更具“语法糖”而不是真正的改进。 IL会讲一个不同的故事吗?
答案 0 :(得分:8)
泛型内置于C#中,因此它是一种“真正的改进”。因此,为什么运行时协方差和反方差是可能的,以及对泛型类型的反射和基于运行时反射的泛型类型的创建(例如List<T>
,其中T在运行时确定)
这不同于C ++,其中模板在很多方面都是语法糖。编译器实际上为您使用的每个泛型类型生成代码 - 因此Add<T>
会创建Add<int>
,Add<long>
,Add<short>
,Add<MyClass>
等等,如果您是使用这些功能,同样适用于类。这样做的好处主要是运算符和一些其他较小的东西 - 如果每个类型都有一个+运算符,Add<T>(T a, T b)
返回一个+ b,所有类型都可以正常工作。 C#的编译器会抱怨,因为它不能/不能在编译时解析任何类型的运算符声明。此外,C#(不是100%肯定,但可能是90%)为引用类型(如果您正在使用该实现)创建1个泛型类型实现,然后为每个值类型创建1(所以int,long,Decimal,MyStruct等全部根据需要获得自己的实现。
答案 1 :(得分:2)
在java中,泛型是语法糖,但在c#中,它们是内置的。看看这个: www.25hoursaday.com/CsharpVsJava.html