deo*_*oll 9 c# evaluation operators associativity
下面发生了什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class DotNetPad
{
public static void Main(string[] args)
{
int i = 10;
string k = "Test";
Console.WriteLine(i+k);
Console.WriteLine(k+i);
}
}
Run Code Online (Sandbox Code Playgroud)
i
在两种情况下都被转换为字符串.我对运算符优先级的概念感到困惑(虽然这个例子没有显示出很多)和评估方向.有时评估从左到右进行,反之亦然.我不完全了解表达式如何评估的科学...
为什么i
在上面的例子中转换为字符串,而不是实际给出编译错误?
Bro*_*ass 23
从C#规范 - 第7.7.4节添加运算符:
字符串连接:
Run Code Online (Sandbox Code Playgroud)string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
当一个或两个 操作数的类型为字符串时,binary +运算符执行字符串连接.如果字符串连接的操作数为null,则替换空字符串.否则,通过调用从类型对象继承的虚拟ToString方法,将任何非字符串参数转换为其字符串表示形式.如果ToString返回null,则替换空字符串.
Eri*_*ert 18
我对运营商优先级和评估方向的想法感到困惑.
不,你不是.这经常被混淆,是的,但这不是你困惑的事情,因为评估的优先级和顺序都与整数是否转换为字符串的问题相关,或者为什么将整数添加到字符串是合法的.
首先要让您对自己困惑的事情不以为然,规则很简单:
这就是你需要知道才能做到的.假设Q()返回一个带有setter的索引器的对象,其他方法都返回整数:
Q()[R()] = A() * B() + C() / D();
Run Code Online (Sandbox Code Playgroud)
根据优先级和关联性括起来:
Q()[R()] = ( ( A() * B() ) + ( C() / D() ) );
Run Code Online (Sandbox Code Playgroud)
现在,每个子表达式都是从左到右进行评估的.每个子表达式,包括本身都有子表达式的子表达式.所以这相当于程序:
var q = Q();
var r = R();
var a = A();
var b = B();
var t1 = a * b;
var c = C();
var d = D();
var t2 = c / d;
var t3 = t1 + t2;
Run Code Online (Sandbox Code Playgroud)
最后用索引r和值t3调用q上的索引setter.
请注意,每个子表达式向左每子表达式向右前评估.A() * B()
是剩下的C() / D()
,所以它首先发生.
这与你的问题没有任何关系.你的问题是基于误解.
我想知道为什么我在上面的例子中转换为字符串,并没有实际给出编译错误
这是你的误解.i
是不被转换为字符串.它正在被转换为object
.您的计划完全等同于:
int i = 10;
string k = "Test";
string t1 = System.String.Concat((object)i, (string)k);
Console.WriteLine(t1);
string t2 = System.String.Concat((string)k, (object)i);
Console.WriteLine(t2);
Run Code Online (Sandbox Code Playgroud)
如您所见,首先没有转换i
为字符串.i
通过装箱转换转换为对象,然后传递给String.Concat
方法.然后该方法调用object.ToString()
盒装整数.
因此,处理上半部分:
我想知道为什么我在上面的例子中转换为字符串,并没有实际给出编译错误
下半部分是:为什么没有编译错误?
为什么会出现编译错误?C#规范说你可以将任何字符串添加到任何对象,或任何对象添加到任何字符串.int是一个对象,因此您可以将其添加到字符串中.
在这两种情况下,你已经得到了+
与字符串作为运营商一个操作数.没有涉及重载的用户定义运算符,因此编译器将使用这两者作为字符串连接情况.
据我所知,C#编译器将只不使用字符串连接为一个场景x + y
,其中任一 x
或者y
是string
在编译时表达,如果有一个用户定义的过载,例如XName operator +(XNamespace, string)
运营商.