简体   繁体   中英

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

In C# why I can call

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

1 and "1" are constant literals so why object.ToString() is not causing errors?

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?

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?

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. 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. So why is 1.ToString() not causing errors?

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 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; the thing that comes next should be a digit. So why is 1.ToString() not causing errors?

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. (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 .

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()

So 1 is of type System.Int32 .

Therefore you can call ToString() for them.

The IL generated for this is something like this:

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. That, specifically, is the instruction that actually "creates" the the System.Int32 value object.

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:

bool isObject = (1 is object);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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