为什么“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
,所以编译器使用重载决策规则来决定哪个运算符(int
,uint
,long
,ulong
,float
,double
decimal
)是最好的。 - 这些解决规则说,看哪个是最好的function …几乎可以说,看看哪个参数types提供了从
char
最好的转换 。 -
int
出long
,float
和double
因为你可以隐式转换为这些types,而不是回来。 -
int
beatsuint
和ulong
因为…最好的转换规则说明了这一点。
这是怎么发生的隐式转换 ( “一个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。