字符 + 字符 = 整数?为什么
本文关键字:字符 为什么 整数 | 更新日期: 2023-09-27 18:16:07
为什么在 C# 结果中添加两个char
到int
类型?
例如,当我这样做时:
var pr = 'R' + 'G' + 'B' + 'Y' + 'P';
pr
变量变为int
类型。我希望它是一个值为 "RGBYP"
的 string
类型。
为什么 C# 设计成这样?添加两个char
的默认实现不是应该导致连接char
s而不是int
的string
吗?
编码到 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
,其中T
是int
、uint
、long
和ulong
中的第一个,可以完全表示两个操作数的所有可能值。
所以对于一个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。
char
或System.Char
是整型:
一个整数类型,表示值介于 0 和 65535 之间的无符号 16 位整数。类型的可能值集对应于 Unicode 字符集。
这意味着它的行为与uint16
或System.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
呢?