在这种情况下,为什么整数转换为字符串?

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节添加运算符:

字符串连接:

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);
Run Code Online (Sandbox Code Playgroud)

一个或两个 操作数的类型为字符串时,binary +运算符执行字符串连接.如果字符串连接的操作数为null,则替换空字符串.否则,通过调用从类型对象继承的虚拟ToString方法,将任何非字符串参数转换为其字符串表示形式.如果ToString返回null,则替换空字符串.

  • 谢谢 - 无法快速达到规范:) (2认同)

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是一个对象,因此您可以将其添加到字符串中.


Jon*_*eet 8

在这两种情况下,你已经得到了+与字符串作为运营商一个操作数.没有涉及重载的用户定义运算符,因此编译器将使用这两者作为字符串连接情况.

据我所知,C#编译器将只不使用字符串连接为一个场景x + y,其中任一 x或者ystring在编译时表达,如果有一个用户定义的过载,例如XName operator +(XNamespace, string)运营商.