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 whyToString()
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 , likex
, so why is1.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 thethis
in the method is aref
to a variable. So why is1.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 is1.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.