通用语法糖或真正的改进
我对以下方法调用有疑问:
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 是否讲述了不同的故事?
I have a question regarding the following method calls:
var ctl1 = this.FindControlRecursively("SomeField") as HiddenField;
var ctl = this.FindControlRecursively<HiddenField>("SomeField");
Here's IL for these two calls:
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)
I've always thought in this situation, the generic version of this method was more "syntactic sugar" vs. true improvement. Is the IL telling a different story?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
泛型内置于 C# 中,因此它是“真正的改进”。因此,为什么运行时协变和逆变是可能的,以及对泛型类型的反射和基于运行时反射的泛型类型创建(例如
List
其中 T 是在运行时确定)。这与 C++ 不同,在 C++ 中,模板在很多方面都是语法糖。编译器实际上为您使用的每种泛型类型生成代码 - 因此
Add
将创建Add
、Add
、Add
、Add
等(如果您使用这些函数),类也同样如此。这样做的好处主要是运算符和其他一些较小的东西 - 如果每个类型都有一个 + 运算符,并且Add(T a, T b)
返回 a + b,则所有类型会工作得很好。 C# 的编译器会抱怨,因为它无法/不会在编译时解析任何和所有类型的运算符声明。此外,C#(不是 100% 确定,但可能是 90%)为引用类型创建 1 个泛型类型实现(如果您正在使用该实现),然后为每个值类型创建 1 个泛型类型实现(因此 int、long、Decimal、MyStruct 等都根据需要获得他们自己的实现)。Generics are built into C#, so it is a "true improvement". Hence why run-time co-variance and contra-variance is possible, as well as reflection on generic types and run-time reflection-based creation of generic types (such as
List<T>
where T is determined at run-time).This differs from C++, where templates are, in a lot of ways, syntactic sugar. The compiler actually generates code for each generic type you use - so
Add<T>
would createAdd<int>
,Add<long>
,Add<short>
,Add<MyClass>
, and so on if you were using those functions, and likewise for classes. The benefit of this is primarily operators and a few other smaller things - if each of those types has a + operator, andAdd<T>(T a, T b)
returns a + b, all types will work just fine. C#'s compiler would complain because it can't/doesn't resolve the operator declaration for any-and-all types at compile time. Moreover, C# (not 100% sure, but maybe 90%) creates 1 generic type implementation for reference types (if you're using that implementation) and then 1 for each value type (so int, long, Decimal, MyStruct, etc all get their own implementations, as needed).在 java 中,泛型是语法糖,但在 c# 中,它们是内置的。看看这个:
www.25hoursaday.com/CsharpVsJava.html
In java, generics are syntactic sugar but in c#, they are built in. look at this:
www.25hoursaday.com/CsharpVsJava.html