编辑:此问题基于GetType()返回字符串的误解。
我试图更好地处理C#的工作原理,所以这个问题更具理论性而非实际性。
据我了解,在值类型上调用GetType需要装箱,然后调用方法。但是由于值类型不能继承,但是类型在编译时是已知的,那么为什么编译器只能用字符串文字替换对GetType()的调用?
或者这是可以完成的事情,但是并不是必要的,因为无论如何都不需要在未装箱的值类型上调用GetType?
答案 0 :(得分:5)
如果您没有误解GetType返回字符串,请考虑您可能会问过的问题。编译器可以编译
Foo foo = whatever;
Type t = foo.GetType();
as
Type t = typeof(Foo);
是的,这将是一个合法的优化。编译器没有进行这种优化,因为当编译团队进行优化实际上有所作为时,浪费编译团队的时间进行优化。让我们考虑一下拟议的优化。
new GetType
上是否有Foo
方法?如果是这样,那么它可以做任何事情。编译器团队必须检测对原始GetType
的调用。然后编写测试用例,确保在这些情况下不应用优化。Foo?
而不是Foo
的情况下,这些副作用包括可能的空取消引用异常,因此您必须在编译器中具有特殊情况。< / LI>
因此,出于所有这些原因,优化成本高于其产生的效益。
有关如何评估建议的优化的更长但类似的讨论,请参阅昨天的答案:Weird behaviour of c# compiler due caching delegate
答案 1 :(得分:2)
在未装箱的值类型中,GetType
将始终返回变量的类型。您已经知道变量的类型,那么开始的优势是什么?如果您想要名称,只需在类型上使用nameof
:
var i = 1;
var iKnowTheType = nameof(System.Int32); //is this evaluated at compile time?
var s = "Int32";
var areSame = ReferenceEquals(iKnowTheType, s); //returns true!
iKnowTheType
和s
是相同的字符串,这意味着nameof(System.Int32)
和文字"Int32"
基本相同(请参阅{ {3}}有关此主题的更准确信息。)
GetType
返回对象的运行时类型。在未装箱的值类型中,它将始终是变量的类型,但这里的关键点是在运行时评估类型:
var i = 1;
var iDontKnowTheType = i.GetType().Name;
var s = "Int32";
var areSame = ReferenceEquals(iDontKnowTheType, s); //returns false!
var areEqual = iDontKnowTheType == s; //returns true
这里,编译器可以实习iDontKnowTheType
,因为在运行时会评估特定的string
。
答案 2 :(得分:1)
GetType()
会返回Type
个对象。该对象在编译时不存在,仅在运行时存在。
此外,该对象还附加了大量元数据和其他运行时数据,因此它不仅可以用于“类型名称比较”,还可以考虑反射和序列化。