6

我有一个简单的问题,但我很惊讶。

此代码有效:

int itemID = 1;
string dirPath = @"C:\" + itemID + @"\abc";

为什么我不必itemID.ToString()在这种情况下做?

4

6 回答 6

13

来自MSDN

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

根据其他答案中的一些评论,稍微扩展我的答案......

这个过程不仅仅是“语法糖”或便利。它是称为运算符重载的核心 C# 语言功能的结果。在 + 运算符和字符串 + 重载的情况下,提供重载作为抽象字符串类内部的一种手段,这是良好设计原则的核心基础。+ 字符串重载通过确保它永远不会返回空值来提供类型安全,而不是为无法使用该.ToString()方法转换的任何操作数返回一个空字符串。但是,即使自定义复杂类型(不仅仅是基元)也可以添加到字符串中,假设它们具有.ToString()重载,而不会知道 String 类型的实现有什么不同。

运算符重载是一个主要的语言特性,更多的人应该学会利用它的力量。

于 2013-09-10T15:09:48.340 回答
8

+in 字符串连接被转换为调用,它在每个对象上string.Concat内部调用无参数。ToString

string.Concate 方法 - MSDN

该方法通过调用该对象的无参数 ToString 方法来连接 args 中的每个对象;它不添加任何分隔符。

编辑:

这是ILSpy中的样子 在此处输入图像描述

于 2013-09-10T15:10:46.580 回答
6

+ 运算符有许多重载。其中三个如下:

运算符 +(字符串 a,字符串 b)

运算符 +(字符串 a,对象 b)

运算符 +(对象 a,字符串 b)

您的代码正在使用运算符的第二个重载。

该运算符将在确定为匹配项后将其转换为对 的调用string.Concat,该调用可以将任意数量的对象(类型object为 )作为其参数。

在 的定义中string.Concat,它将调用ToString所有参数(首先检查它们是否为空)以获取它们的字符串值,这就是将被连接的内容。

由于所有这些,您始终可以将任何对象与字符串连接,并且它将使用该对象的ToString方法进行编译和执行。

于 2013-09-10T15:19:10.797 回答
1

因为它是由编译器自动完成的。

基本上:

  string a = "abc" + 1; 

编译为:

  string a = string.Concat((object)"abc", (object)1);

它只是语法糖。虽然我个人不喜欢自动转换。

参考:http Concat: //msdn.microsoft.com/en-us/library/kbseaaft.aspx

于 2013-09-10T15:08:20.737 回答
0

一个非常有趣的问题。

让我们看看您的示例的 IL 代码:

 ldstr     "C:\\"
 ldloc.0
 box       int
 ldstr     "\\abc"
 call      string System.String.Concat(object, object, object)

后面调用的函数是 System.String.Concat,它需要 3 个对象!

让我们深入了解 .NET 源代码:

public static String Concat(Object arg0, Object arg1, Object arg2) {
        Contract.Ensures(Contract.Result<String>() != null);
        Contract.EndContractBlock();

        if (arg0 == null)
        { 
            arg0 = String.Empty; 
        }

        if (arg1==null) {
            arg1 = String.Empty;
        }

        if (arg2==null) {
            arg2 = String.Empty; 
        } 
           return Concat(arg0.ToString(), arg1.ToString(), arg2.ToString());
   }  

如您所见ToString(),它将被称为但稍后!这令人印象深刻的是微软人正在做的事情!

于 2013-09-10T15:30:11.993 回答
0

这是一个语言特性。ToString()在使用运算符进行字符串连接时在对象内部调用+

这样做的根本原因仅仅是对开发人员的方便(并且可能由于ToString()调用较少而增加了可读性,但它也可能诱使您认为对象是字符串,而实际上它可以是任何东西)。

对于 C#,可能采用了 Java 的行为,这是相同的。问一个问题可能很有趣,为什么首先在 Java 中引入了这一点。

于 2013-09-10T15:10:11.433 回答