简体   繁体   English

C#为什么我可以在常量上调用对象扩展方法?

[英]C# Why i can call object extension methods on constants?

In C# why I can call 在C#中为什么我可以打电话

var intStr = 1.ToString();
var strStr = "1".ToString();

1 and "1" are constant literals so why object.ToString() is not causing errors? 1和“1”是常量文字所以为什么object.ToString()不会导致错误?

Why I can call object extension methods on constants? 为什么我可以在常量上调用对象扩展方法?

Those aren't extension methods. 那些不是扩展方法。

1 and "1" are constants so why ToString() is not causing errors? 1"1"是常量,为什么ToString()不会导致错误?

Your question asks "why not" without ever explaining why you think this should be a problem in the first place . 你的问题在没有解释为什么你认为这首先应该成为一个问题的问题时会问“为什么不”。 When asking questions of this form in the future please say why you think the operation ought to be disallowed. 在将来询问此表格的问题时,请说明为什么您认为该行动应该被禁止。

So let's try to read your mind. 所以让我们试着读懂你的想法。 Here's a question you could have asked: 这是你可能会问的一个问题:

1 and "1" are literals but the left hand side of a dot must be a symbol , like x , so why is 1.ToString() not causing errors? 1"1"文字,但点的左侧必须是符号 ,如x ,那么为什么1.ToString()不会导致错误?

The supposition is incorrect. 假设不正确。 The thing on the left hand side of a member access dot must be an expression. 成员访问点左侧的东西必须是表达式。 There are restrictions on that expression; 这种表达有限制; for example, it cannot be a void-returning method call. 例如,它不能是返回void的方法调用。 But there is no restriction on it being a literal. 但它没有限制它是文字。

Here's another question you could have asked: 这是你可能会问的另一个问题:

1 is a constant of value type but the receiver of a method of a value type must be a variable, because the this in the method is a ref to a variable. 1值类型常量,值类型的方法的接收者必须是变量,因为方法中的this是对变量的ref So why is 1.ToString() not causing errors? 那么为什么1.ToString()不会导致错误呢?

If the receiver of a method call is of a value type and the this has to be of ref type but the receiver expression is not classified as a variable then the compiler copies the value to a temporary variable and passes a ref to that variable. 如果方法调用的所述接收器是一个值的类型,并且this必须的ref类型,但是接收机表达不被分类为一个变量则编译器拷贝的值到一个临时变量,并传递一个ref给该变量。

This means that if the method mutates the variable, the mutation is lost because it is performed on a copy. 这意味着如果方法改变变量,则突变会丢失,因为它是在副本上执行的。 This is yet another reason why mutable value types are a bad practice. 这是可变值类型是一种不好的做法的另一个原因。 It is easy to lose a mutation accidentally! 不小心丢失突变很容易!

Here's another question you could have asked: 这是你可能会问的另一个问题:

1. is the beginning of a float, double or decimal literal; 1.是浮点数,双精度或十进制数字的开头; the thing that comes next should be a digit. 接下来的事情应该是一个数字。 So why is 1.ToString() not causing errors? 那么为什么1.ToString()不会导致错误呢?

The question makes an incorrect supposition. 这个问题做出了错误的假设。 The lexer checks whether the thing that follows the dot is a digit; 词法分析器检查点后面的东西是否是数字; if it is then it keeps lexing the literal as a float, double or decimal. 如果它然后它保持lexing文字作为浮点数,双精度或小数。 (Which it is will be determined by the suffix, if any.) If the thing that follows the dot is not a digit then the lexer lexes the dot as a member access dot and starts lexing a new token for the ToString . (它将由后缀确定,如果有的话。)如果点后面的东西不是数字,则词法分析器将点作为成员访问点,并开始为ToString新的令牌。

They are initialised from constant literals (in the program text), but they are actually objects (in that they are logically treated as objects), and all objects implement ToString() 它们是从常量文字(在程序文本中)初始化的,但它们实际上是对象(因为它们在逻辑上被视为对象),并且所有对象都实现了ToString()

So 1 is of type System.Int32 . 所以1System.Int32类型。

Therefore you can call ToString() for them. 因此,您可以为它们调用ToString()

The IL generated for this is something like this: 为此生成的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()

Note that the ldc.i4.1 is a special instruction that pushes a System.Int32 with value 1 onto the stack. 请注意, ldc.i4.1是一个特殊指令,它将值为1的System.Int32入堆栈。 That, specifically, is the instruction that actually "creates" the the System.Int32 value object. 具体而言,这是实际“创建” System.Int32值对象的指令。

Also note that although System.Int32 is a value type, it is also treated as an object, so that the following statement is always true: 另请注意,尽管System.Int32是值类型,但它也被视为对象,因此以下语句始终为true:

bool isObject = (1 is object);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM