字符 + 字符 = 整数?为什么

本文关键字:字符 为什么 整数 | 更新日期: 2023-09-27 18:16:07

为什么在 C# 结果中添加两个charint类型?

例如,当我这样做时:

var pr = 'R' + 'G' + 'B' + 'Y' + 'P';

pr变量变为int类型。我希望它是一个值为 "RGBYP"string 类型。

为什么 C# 设计成这样?添加两个char的默认实现不是应该导致连接char s而不是intstring吗?

字符 + 字符 = 整数?为什么

编码到 char 的文档,它可以隐式转换为整数值。char 类型未定义自定义operator +因此使用整数类型。

Eric Lippert在他的博客文章"为什么char隐式转换为ushort,反之亦然?"的第一条评论中很好地解释了没有隐式转换为字符串的基本原理:

在 v1.0 中考虑过。6月6日的语言设计笔记1999年说:"我们讨论了这种转换是否应该存在,并且决定提供第三种方法来做到这一点会很奇怪转换。[该语言] 已经支持 c.ToString(( 和 new字符串(c("。

(感谢JimmiTh找到这句话(

char是一种值类型,这意味着它有一个数值(它的 UTF-16 Unicode 序号(。但是,它不被视为数字类型(如 int、float 等(,因此,没有为 char 定义 + 运算符。

但是,可以将char类型隐式转换为数字int类型。因为它是隐式的,所以允许编译器根据 C# 规范中列出的一组优先级规则为你进行转换。 int是通常尝试的第一件事。这使得+运算符有效,因此这就是执行的操作。

要执行所需的操作,请从空字符串开始:

var pr = "" + 'R' + 'G' + 'B' + 'Y' + 'P';

与 char 类型不同,字符串类型为 Object 定义了一个重载 + 运算符,该运算符使用 ToString() 将第二个术语(无论它是什么(转换为字符串,然后再将其连接到第一个术语。这意味着不执行隐式强制转换;您的 pr 变量现在被推断为字符串,并且是所有字符值的串联。

因为单个字符可以转换为 Unicode 值,并且可以轻松地存储为整数,占用的空间比单个字符串少。

从 MSDN:

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

字符是整数类型。它不是一个字符,而是一个数字!

'a'只是一个数字的简写。

因此,添加两个字符会产生一个数字。

看看这个关于添加字节的问题,虽然违反直觉,但它是一回事。

规范

的另一个相关部分,在第 4.1.5 节(整型(中将char定义为整型:

对于二进制+...运算符,操作数转换为类型 T,其中 Tintuintlongulong 中的第一个,可以完全表示两个操作数的所有可能值。

所以对于一个char,两者都被转换为int,然后作为int s添加。

关键是,许多 C# 概念都来自 C++ 和 C。

在这些语言中,单个字符常量(如"A"(表示为它们的 Ascii 值,尽管人们可能期望,但它的类型不是 char 而是 int(是的,"A"是一个 int,与写 65 相同(。

因此,所有这些值的相加就像编写一系列 ascii 字符代码,即

   var pr= 82 + 71 + 66 + ...;

这在某些时候一直是C/C++的设计决策(它可以追溯到70年代的C(。

来自 MSDN:

隐式转换可能发生在很多情况下,包括方法 调用和赋值语句。

字符可以隐式转换为 ushort、int、uint、long、ulong、float、double 或十进制。因此,该赋值操作隐式将 char 转换为 int。

charSystem.Char是整型:

一个整数类型,表示值介于 0 和 65535 之间的无符号 16 位整数。类型的可能值集对应于 Unicode 字符集。

这意味着它的行为与uint16System.UInt16完全一样,因此使用+运算符添加字符会增加整数值,因为+运算符在char中没有重载。

要将单个字符连接成字符串,请使用 StringBuilder.Append(char)new String(char[])

如前所述,这是因为 char 具有包含其 unicode 值的 Int32 值。

如果要将字符连接成字符串,可以执行以下操作之一:

将字符数组传递给新字符串:

var pr = new string(new char[] { 'R', 'G', 'B', 'Y', 'P' });

使用 StringBuilder:

StringBuilder sb = new StringBuilder();
sb.Append('R');
etc...

从字符串开始:

var pr = string.Empty + 'R' + 'G' + 'B' + 'Y' + 'P';

将每个转换为字符串(或者只有第一个也可以正常工作(:

var pr = (string)'R' + (string)'G' + (string)'B' + (string)'Y' + (string)'P';

它不应该,因为那样效率低下。如果想像这样连接字符,他们应该使用字符串生成器。否则,每次添加都会创建一个临时内存来保存串联的部分字符串,这意味着在您的示例中必须进行 4 个临时内存分配。

Char 是 16 位整数值的文本表示形式。你只是把整数加在一起。如果要连接字符,则必须将它们转换为字符串。

1( 定义 (MSDN(:

char 关键字用于声明 16 位字符,用于表示世界上大多数已知的书面语言。


2(为什么char喜欢数字类型?

A char can be implicitly converted to a numeric type.

字符更接近整数而不是字符串。字符串只是 char 对象的集合,而整数可以表示 char,反之亦然。


3( 示例

您可以简单地将第一个字符转换为字符串,以智取编译器:

var pr = 'R'.ToString() + 'G' + 'B' + 'Y' + 'P';

您还可以定义一个 char 数组,然后使用字符串构造函数:

char[] letters = { 'R', 'G', 'B','Y', 'P' };
string alphabet = new string(letters);

如果你想单独打印出一个字符,你总是必须把它转换成一个字符串,以获得它的文本表示:

 var foo1 = 'F';
 MessageBox.Show(foo1.ToString());

为什么 C# 设计成这样?不是默认实现 添加两个字符应生成一个字符串,该字符串连接 字符,不是整数?

你的意图与你想要完成的是不正确的。字符串不是字符的添加,字符串是"单例"字符串的添加。

所以 "a"+"b"=>"ab",如果你考虑到字符串的 + 运算符是重载的,这是绝对正确的。因此,"a"代表ASCII字符65,说"a"+"b"是131是完全一致的。

因为一个字符加上另一个字符可以超过一个字符变量允许的最大值,这就是为什么该操作的结果被转换为 int 变量的原因。

您假设char是字符串类型。char的值可以用单引号之间的字符值表示,但如果它有帮助,您应该将其视为提供可读性的抽象,而不是强迫您作为开发人员记住基础值。实际上,它是一种数值类型,因此您不应期望任何字符串操作函数都适用。

至于为什么char + char = int?我不知道。当然,提供对Int32的隐式转换可以减轻算术溢出,但是为什么short + short没有隐式类型化int呢?