【问题标题】:Why is the integer converted to string in this case?为什么在这种情况下将整数转换为字符串?
【发布时间】:2012-05-12 00:21:06
【问题描述】:

下面发生了什么?

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);
    }
}

i 在这两种情况下都被转换为字符串。我对运算符优先级的概念(尽管这个例子没有显示太多)和评估方向感到困惑。有时评估是从左到右进行的,反之亦然。我不完全了解如何评估表达式的科学......

为什么上面的例子中i被转换成字符串,实际上并没有给出编译错误?

【问题讨论】:

    标签: c# operators evaluation associativity


    【解决方案1】:

    在这两种情况下,您都有+ 运算符,其中字符串作为操作数的一个。不涉及重载的用户定义运算符,因此编译器将使用 both 作为字符串连接情况。

    据我所知,C# 编译器仅不会对 x + y 的场景使用字符串连接,其中 either xystring 表达式如果存在用户定义的重载,则为编译时,例如XName operator +(XNamespace, string) 运算符。

    【讨论】:

      【解决方案2】:

      来自 C# 规范 - 第 7.7.4 节加法运算符:

      字符串连接

      string operator +(string x, string y);
      string operator +(string x, object y);
      string operator +(object x, string y);
      

      二元+运算符在一个或两个时执行字符串连接 操作数是字符串类型。如果字符串连接的操作数是 null,则替换为空字符串。否则,任何非字符串 参数通过调用 从类型对象继承的虚拟 ToString 方法。如果 ToString 返回 null,替换为空字符串。

      【讨论】:

      • 谢谢 - 无法快速了解规范 :)
      【解决方案3】:

      实际上“+”运算符是用于连接的。在 int 和 string 之间进行连接将给出一个字符串(自动将 int 转换为字符串)

      【讨论】:

      • 在 Console.WriteLine 中对数值变量使用“+”将导致输出中数值变量的总和。
      【解决方案4】:

      我对运算符优先级和评估方向的想法感到困惑。

      不,你不是。这经常被混淆,是的,但这不是你混淆的事情,因为优先级和评估顺序都与整数是否转换为字符串或为什么它是合法的问题相关将整数添加到字符串中。

      首先要让您对您声称感到困惑的点感到困惑,规则非常简单:

      • 表达式根据运算符优先级和关联性加括号。
      • 子表达式按从左到右的顺序计算。

      这就是你需要知道的一切。假设 Q() 返回一个对象,该对象有一个带有 setter 的索引器,而其他方法都返回整数:

      Q()[R()] = A() * B() + C() / D();
      

      根据优先级和关联性用括号括起来:

      Q()[R()] = ( ( A() * B() ) + ( C() / D() ) );
      

      现在每个子表达式都是从左到右计算的。 每个子表达式,包括本身具有子表达式的子表达式。所以这相当于程序:

      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;
      

      最后,q 上的索引设置器被调用,索引为 r,值为 t3。

      请注意,左侧的每个子表达式都会在右侧的每个子表达式之前进行计算。 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);
      

      如您所见,首先没有从i 到字符串的转换。 i 通过装箱转换转换为对象,然后传递给String.Concat 方法。然后该方法在装箱的整数上调用object.ToString()

      这样处理前半部分:

      我想知道为什么我在上面的例子中被转换为字符串,而实际上并没有给出编译错误

      后半部分是:为什么没有编译错误?

      为什么会出现编译错误? C# 规范说您可以将任何字符串添加到任何对象,或将任何对象添加到任何字符串。 int 是一个对象,因此您可以将其添加到字符串中。

      【讨论】:

      • 我喜欢你的回答。但我不确定最后一部分:如果按照规范你的意思是 + 运算符是按照@brokenglass 提到的方式定义的,我同意......
      猜你喜欢
      • 2015-11-19
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      相关资源
      最近更新 更多