[英]C# Why i can call object extension methods on constants?
在C#中为什么我可以打电话
var intStr = 1.ToString();
var strStr = "1".ToString();
1和“1”是常量文字所以为什么object.ToString()
不会导致错误?
为什么我可以在常量上调用对象扩展方法?
那些不是扩展方法。
1
和"1"
是常量,为什么ToString()
不会导致错误?
你的问题在没有解释为什么你认为这首先应该成为一个问题的问题时会问“为什么不”。 在将来询问此表格的问题时,请说明为什么您认为该行动应该被禁止。
所以让我们试着读懂你的想法。 这是你可能会问的一个问题:
1
和"1"
是文字,但点的左侧必须是符号 ,如x
,那么为什么1.ToString()
不会导致错误?
假设不正确。 成员访问点左侧的东西必须是表达式。 这种表达有限制; 例如,它不能是返回void的方法调用。 但它没有限制它是文字。
这是你可能会问的另一个问题:
1
是值类型的常量,但值类型的方法的接收者必须是变量,因为方法中的this
是对变量的ref
。 那么为什么1.ToString()
不会导致错误呢?
如果方法调用的所述接收器是一个值的类型,并且this
必须的ref
类型,但是接收机表达不被分类为一个变量则编译器拷贝的值到一个临时变量,并传递一个ref
给该变量。
这意味着如果方法改变变量,则突变会丢失,因为它是在副本上执行的。 这是可变值类型是一种不好的做法的另一个原因。 不小心丢失突变很容易!
这是你可能会问的另一个问题:
1.
是浮点数,双精度或十进制数字的开头; 接下来的事情应该是一个数字。 那么为什么1.ToString()
不会导致错误呢?
这个问题做出了错误的假设。 词法分析器检查点后面的东西是否是数字; 如果它然后它保持lexing文字作为浮点数,双精度或小数。 (它将由后缀确定,如果有的话。)如果点后面的东西不是数字,则词法分析器将点作为成员访问点,并开始为ToString
新的令牌。
它们是从常量文字(在程序文本中)初始化的,但它们实际上是对象(因为它们在逻辑上被视为对象),并且所有对象都实现了ToString()
所以1
是System.Int32
类型。
因此,您可以为它们调用ToString()
。
为此生成的IL是这样的:
L_0001: ldc.i4.1
L_0002: stloc.1
L_0003: ldloca.s CS$0$0000
L_0005: call instance string [mscorlib]System.Int32::ToString()
请注意, ldc.i4.1
是一个特殊指令,它将值为1的System.Int32
入堆栈。 具体而言,这是实际“创建” System.Int32
值对象的指令。
另请注意,尽管System.Int32是值类型,但它也被视为对象,因此以下语句始终为true:
bool isObject = (1 is object);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.