为什么“hello”+ +“/”+“world”==“hello47world”?

对于这个C#, a==true

 bool a = "hello" + '/' + "world" == "hello/world"; 

而对于这个C#, b==true

 bool b = "hello" + + '/' + "world" == "hello47world"; 

我想知道这是怎么回事,更重要的是,为什么C#语言架构师会select这种行为呢?

第二个+char转换为int ,并将其添加到string中。 /为47的ASCII值,然后由另一个+运算符转换为string。

斜杠之前的+运算符将其隐式转换为intforms。 请参阅MSDN上的+运算符 ,并查看“unary plus”。

数字types的一元操作的结果只是操作数的值。

我其实是通过查看+运营商实际上在调用什么的。 (我认为这是一个ReSharper或VS 2015function)

在这里输入图像说明

在这里输入图像说明

那是因为你正在使用一元运算符+ 。 它和一元运算符类似-但它并不改变操作数的符号,所以它的唯一作用是隐式地把字符'/'转换成一个int

+'/'的值是+'/'的字符代码,即47。

代码与以下内容相同:

 bool b = "hello" + (int)'/' + "world" == "hello47world"; 

为什么,我听到你问,是特殊处理的运算符int operator +(int x)而不是许多其他一元罚+运算符中的一个 ?

  • 一元运算符重载parsing规则首先要查看用户定义的一元运算符,但由于char没有任何这些运算符,因此编译器会查看预定义的一元运算符。
  • 很明显,这些都没有一个char ,所以编译器使用重载决策规则来决定哪个运算符( intuintlongulongfloatdouble decimal )是最好的。
  • 这些解决规则说,看哪个是最好的function …几乎可以说,看看哪个参数types提供了从char 最好的转换 。
  • intlongfloatdouble因为你可以隐式转换为这些types,而不是回来。
  • int beats uintulong因为…最好的转换规则说明了这一点。

这是怎么发生的隐式转换“一个char可以隐式转换为ushort,int,uint,long,ulong,float,double或decimal。”char MSDN )。

最简单的复制forms可以find

 int slash = +'/'; // 47 

字符内部是一个结构。 “目的:这是表示一个Unicode字符的值类”char.cs ms referencesource ),并且结构可以被隐式转换的原因是因为它实现了IConvertible接口。

 public struct Char : IComparable, IConvertible 

具体来说就是用这段代码

 /// <internalonly/> int IConvertible.ToInt32(IFormatProvider provider) { return Convert.ToInt32(m_value); } 

IConvertible接口在代码中注释

// IConvertible接口表示一个包含值的对象。 这个
//接口由System命名空间中的以下types实现:
//布尔,Char,SByte,Byte,Int16,UInt16,Int32,UInt32,Int64,UInt64,
// Single,Double,Decimal,DateTime,TimeSpan和String。

回顾struct的目的(作为unicode字符的值的代表),显然这种行为在语言中的意图是提供一种将值转换为支持types的方式。 IConvertible继续说

//由System.XXX值类提供的IConvertible的实现
//简单地转发到适当的Value.ToXXX(YYY)方法(一个描述
// Value类如下所示)。 在Value.ToXXX(YYY)方法的情况下
//不存在(因为不支持特定的转换)
// IConvertible实现应该只是抛出一个InvalidCastException。

其中明确指出,不支持的转换会抛出exception。 还明确指出,将字符转换为整数将给出该字符的整数值。

ToInt32(Char)方法返回一个32位有符号整数,表示值参数的UTF-16编码代码单元。 Convert.ToInt32方法(Char) MSDN

总而言之,这种行为的推理似乎是不言而喻的。 char的整数值具有“UTF-16编码的代码单元”的含义。 反斜杠的值是47。

作为值转换呈现的结果,因为char是一个内置的数字types,隐式转换为加号的整数是在编译时完成的。 这可以看出,在一个小程序(linqpad的作品来testing这个)上面的简单例子的重用,

 void Main() { int slash = +'/'; Console.WriteLine(slash); } 

 IL_0000: ldc.i4.s 2F IL_0002: stloc.0 // slash2 IL_0003: ldloc.0 // slash2 IL_0004: call System.Console.WriteLine IL_0009: ret 

'/'简单地转换为2F的hex值(十进制47),然后从那里使用。

 + '/' 

为您提供字符“/”的UTF-16 (decimal) 47字符代码,@Guffa已经向您解释了原因。

在c#中,char是用单引号表示的,例如'/',char前面的+运算符作为一元运算符,并要求编译器提供字符“/”的UTF值为47。