为什么将char
C# 结果中的两个添加到int
类型中?
例如,当我这样做时:
var pr = 'R' + 'G' + 'B' + 'Y' + 'P';
pr
变量成为一种类型int
。我希望它是string
一个值为 的类型"RGBYP"
。
为什么 C# 是这样设计的?添加两个 s 的默认实现不char
应该导致string
连接char
s 的 a,不是int
吗?
根据char的文档,它可以隐式转换为整数值。该char
类型没有定义自定义operator +
,因此使用了整数类型。
Eric Lippert 在他的博客文章“为什么 char 隐式转换为 ushort 但反之不行?”的第一条评论很好地解释了没有隐式转换为字符串的理由。:
它在 v1.0 中被考虑过。1999 年 6 月 6 日的语言设计说明说:“我们讨论了是否应该存在这种转换,并决定提供第三种方法来进行这种转换是很奇怪的。[语言] 已经支持 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 定义了一个重载的 + 运算符,它将第二项(无论它是什么)转换为字符串 using ToString()
,然后再将其连接到第一项。这意味着不执行隐式转换;您的pr
变量现在被推断为字符串,并且是所有字符值的串联。
因为单个 char 可以转换为 Unicode 值,并且可以很容易地存储为整数,占用的空间比单个字符串少。
Char 对象的值是一个 16 位数字(序数)值。
char 是一个整数类型。这不是一个字符,它是一个数字!
'a'
只是数字的简写。
所以添加两个字符会产生一个数字。
关键是,许多 C# 概念都来自 C++ 和 C。
在这些语言中,单个字符常量(如 'A')表示为它们的 Ascii 值,尽管人们可能期望它的类型不是 char 而是 int(是的,'A' 是一个 int,与写作 65 相同)。
因此,所有这些值的相加就像是写了一系列ascii字符代码,即
var pr= 82 + 71 + 66 + ...;
这在某个时候是 C / C++ 中的一个设计决定(它可以追溯到 70 年代的 C)。
规范的另一个相关位,在第 4.1.5 节(整数类型)中定义char
为整数类型:
对于二元
+
... 运算符,操作数被转换为 typeT
,其中T
是 , 的第一个,int
并且可以完全表示两个操作数的所有可能值。uint
long
ulong
所以对于 a char
,两者都被转换为int
然后添加为int
s。
来自MSDN:
隐式转换可能发生在许多情况下,包括方法调用和赋值语句。
char 可以隐式转换为 ushort、int、uint、long、ulong、float、double 或 decimal。因此,赋值操作隐式地将 char 转换为 int。
如前所述,这是因为 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';
A char
orSystem.Char
是一个整数类型:
表示无符号 16 位整数的整数类型,其值介于 0 和 65535 之间。该类型的可能值集对应于 Unicode 字符集。
这意味着它的行为与uint16
or完全一样System.UInt16
,并且使用运算符添加字符+
因此会添加整数值,因为+
运算符没有在 中重载char
。
要将单个字符连接成字符串,请使用StringBuilder.Append(char)
或new String(char[])
。
这不应该,因为那将是低效的。如果想像这样连接字符,他们应该使用字符串生成器。否则,每次添加都会创建一个临时内存来保存连接的部分字符串,这意味着在您的示例中必须进行 4 次临时内存分配。
1)定义(MSDN):
char 关键字用于声明一个 16 位字符,用于表示世界上大多数已知的书面语言。
2) 为什么 char 喜欢数字类型?
A char can be implicitly converted to a numeric type.
char 更接近整数而不是字符串。字符串只是 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());
Char 是 16 位整数值的文本表示。您只是将整数加在一起。如果要连接字符,则必须将它们转换为字符串。
因为一个 char 加上另一个 char 可能超过 char 变量允许的最大值,这就是该操作的结果被转换为 int 变量的原因。
为什么 C# 是这样设计的?添加两个字符的默认实现不应该导致连接字符的字符串,而不是int?
就你想要完成的事情而言,你的意图是不正确的。字符串不是字符的添加,字符串是所谓的“单例”字符串的添加。
所以“a”+“b”=>“ab”,如果你考虑到字符串的 + 运算符被重载,这是绝对正确的。因此 'a' 代表 ASCII 字符 65,完全一致的说法是,'a'+'b' 是 131。
您假设 achar
是字符串类型。a 的值char
可以用单引号之间的字符值表示,但如果有帮助,您应该将其视为提供可读性的抽象,而不是强迫您作为开发人员记住底层值。事实上,它是一种数值类型,因此您不应期望任何字符串操作函数都适用。
至于为什么为什么char + char = int
?我不知道。当然,提供隐式转换 toInt32
会减轻算术溢出,但是为什么short + short
不隐式键入 toint
呢?