【问题标题】:How does the UTF-16 character turns to Number and otherwise turns to charUTF-16 字符如何转为 Number 否则转为 char
【发布时间】:2017-09-04 09:41:06
【问题描述】:

我曾经模拟VAR VS Dynamic 变量,后来我想出了这个:

 dynamic s = 2;
   var w = "";
   var d1 = s + " " + "dynamic test 1";
   var d2 = s + 'd' + ' ' + "dynamic test 2";
   String d3 = s + 'k' + ' ' + "dynamic test 2";
   var d4 = 'd' + "dynamic test 2";

为了简单起见:

我的问题是:

为什么 char dk 变成一个数字,而 d4 变量中的 d 保持其自己的值 d

【问题讨论】:

  • 这不仅是字符而且看看空白' '也变成了一个数字。

标签: c# utf-16


【解决方案1】:

从左到右执行。 因此,先添加整数,然后再添加字符类型将字符转换为整数,然后将其输出附加到字符串。

对于 d4,因为在开始时没有整数,因此在追加之前将字符类型转换为字符串。

解释:

the integer value of 'd' is 100

the value of ' ' is 32

Hence 2 + 100 + 32 = 134. 感谢Paulf 的建议

感谢Corak 的详细解释。 将其添加到答案中,以免错过。

您有一个 int 值 (2) 和一个 char 值 ('d')。你想把它们加在一起。预期的结果是什么? "2d" 将是一个字符串,因此既不是 int 也不是 char。对于大多数人来说,这是出乎意料的,所以这不好。还有什么可能发生? 'd' 可以增加 2。所以结果可能是 'f'。但这仅适用于极少数 int 值。所以决定,int加char得到int,取char的数值。这适用于几乎所有 int 和 char 组合,所以这是选择的行为。

另一方面,您有一个字符值('d')和一个字符串值(“test”)。你想把它们加在一起。预期的结果是什么?像 int + char 那样获取 char 的数值会导致“100test”,这将是非常出乎意料的。此外,object + string(或 string + object)的标准行为是将其隐式转换为 object.ToString() + string。而 'd'.ToString() 将是 "d" (字符串值!)。所以 'd'.ToString() + "test" 会产生 "dtest",这也是预期的行为。所以赢/赢。 ^_^

【讨论】:

  • 为了完成解释,您可以添加 'd' 的整数值为 100 并且 ' ' 的值为 32 - 因此 2 + 100 + 32 = 134。
  • 这个答案被接受,但我需要更多解释一些大师为什么会发生......不使用.ToString()
  • @reds - ToString() 被隐式调用,每当您向string 添加内容时(反之亦然)。
  • @reds - 你有一个 int 值 (2) 和一个 char 值 ('d')。你想把它们加在一起。预期的结果是什么? "2d" 将是 string,所以既不是 int 也不是 char。对于大多数人来说,这是出乎意料的,所以这不好。还有什么可能发生? 'd' 可以增加 2。所以结果可能是'f'。但这仅适用于极少数int 值。所以决定int加上char得到int,取char的数值。这几乎适用于 intchar 的所有组合,因此这是选择的行为。
  • 另一方面,您有一个 char 值 ('d') 和一个 string 值 ("test")。你想把它们加在一起。预期的结果是什么?在int + char 中获取char 的数值会导致"100test",这将是非常意外的。此外,object + string(或string + object)的标准行为是将其隐式转换为object.ToString() + string。而'd'.ToString() 将是"d"string 值!)。所以'd'.ToString() + "test" 产生"dtest",这也是预期的行为。所以赢/赢。 ^_^
【解决方案2】:

因为运算符的优先级和+ 运算符的选定重载。当你看到这一行时:

var d2 = s + 'd' + ' ' + "dynamic test 2";

对于第一个+ 运算符,您在两侧有一个int 和一个char。这里选择了加法运算符的重载int operator +(int x, int y);,它将添加数字和字符(它被隐式转换为int,因为在幕后它具有'd' 的数字表示)。结果是int

PaulF 提供了指向 documentation 的链接,它对 char 说:

Char 对象的值是一个 16 位数字(序数)值。

这就是结果是数字的原因。

第二个+ 运算符的处理方式相同。

第三个+运算符有一个对方的字符串,所以编译器在int变量上隐式调用ToString方法,选择了加法运算符的另一个重载,即:string operator +(object x, string y);连接两个。

您现在可以使用( ) 确定优先级。在这一行:

var d2 = s + ('d' + (' ' + "dynamic test 2"));

这里将首先评估第三个+ 运算符,因此将采用串联重载。结果是一个字符串。第二个运算符将在右侧再次遇到一个字符串,因此它将再次成为相同的上下文,并且将再次调用ToString() 方法并将char(变成字符串)连接起来。当再次到达第一个运算符时,将调用ToString() 方法(现在在int 上,变成一个字符串)将被连接起来。

This post 可能会提供进一步的帮助

编辑

这里是overview over all possible Addition operator overloads

一般而言,数据类型的选择是通过以下方式确定的:

对于 x + y 形式的运算,应用二元运算符重载决议 Section 7.2.4 来选择特定的运算符实现。操作数转换为所选运算符的参数类型,结果类型为运算符的返回类型。

字符串连接的文档说明:

当一个或两个操作数都是字符串类型时,预定义的加法运算符连接操作数的字符串表示形式。

当一个或两个操作数都是字符串类型时,二元 + 运算符执行字符串连接。

【讨论】:

  • 我接受你的回答,但是空白的' ' char 为什么它也变成数字呢?
  • @reds - 因为s + 'd' 导致int。然后是int + ' '。同样,要添加的字符 (' ') 被隐式转换为 int
  • @reds - 查看我对 Aman 的回答的评论,其中解释了价值观和结果
  • @reds 我找到了运算符重载的链接。看看我的编辑
【解决方案3】:

为了避免这样的错误(将 integer scharacter d 相加导致s + (int) 'd')使用字符串插值(或格式化):

  dynamic s = 2;

  var w = "";
  var d1 = $"{s} dynamic test 1";       // s followed by space and dynamic test 1

  // I've preserved 'd' and 'k' to show absence of the errors
  // More natural code is
  // var d2 = $"{s} d dynamic test 2"; 
  var d2 = $"{s} {'d'} dynamic test 2"; // s followed by space then 'd' character ...

  String d3 = $"{s}{'k'} dynamic test 2";
  var d4 = $"{'d'} dynamic test 2";

  ... 

编辑:如果 C# 5.0- 不支持 字符串插值,请尝试使用 formatting

  var d1 = string.Format("{0} dynamic test 1", s);
  var d2 = string.Format("{0} {1} dynamic test 2", s, 'd'); 

  String d3 = string.Format("{0}{1} dynamic test 2", s, 'k');
  var d4 = string.Format"{0} dynamic test 2", 'd');

不要连接字符串:

  1. 连接的可读性较差
  2. 它容易出错(+ 可以是不同的操作 - 添加和连接)

【讨论】:

  • @DmityBychenko 为什么在哪个版本的 VS 这个$ 支持?
  • @reds:字符串插值支持已经出现在 C# 6.0 (VS 2015)中
  • 感谢@DmityBychenko 现在我知道这就是它在 VS 2012 中不起作用的原因。
  • @reds:如果是 C# 5.0 或更低版本,请尝试使用 formatting 而不是 string interpolation,即 var d2 = $"{s} {'d'} dynamic test 2"; 将是 var d2 = strong.Format("{0} {1} dynamic test 2", s, 'd');
【解决方案4】:

如果我是对的,它就像ASCII一样,每个字母对应一个数字

【讨论】:

  • 不完全是。字符集是数字和字符之间的一组映射,称为代码点。编码决定了数字的存储方式。它将一个代码点映射到一个或多个代码单元。代码单元是存储为字节的整数。在 C# 中,char 是一个 UTF-16 代码单元。 UTF-16 是 Unicode 字符集的几种编码之一。 (ASCII 仅在 3 年中专门使用。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 2012-03-30
  • 2010-09-21
  • 2022-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多