【问题标题】:char + char = int? Why?字符 + 字符 = 整数?为什么?
【发布时间】:2021-04-11 23:18:03
【问题描述】:

为什么将 C# 结果中的两个 char 添加到 int 类型?

例如,当我这样做时:

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

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

为什么 C# 是这样设计的?添加两个chars 的默认实现不应该导致连接chars 的string,而不是int

【问题讨论】:

  • 有趣的是您实际上并没有添加chars,因为C# 没有为该类型定义内置的+ 运算符。但是,char 可以隐式转换为 int,因此编译器在进行重载解析时会选择 + 运算符的 int 版本。当然,该运算符的结果是另一个int。 (注意说“当然”有点好笑,因为short + short 实际上是int,而不是另一个short 的“当然”回答!)
  • 继承自 C 的众多特性之一。char 在 C 中是一个整数类型,在 C# 中也是如此。没有很好的理由更改类型的行为(您可以使用其他功能轻松地从单个 chars 创建字符串)会惹恼已经习惯 C/C++ 行为的用户。
  • 在它的最基本级别中,char 不是 int 类型吗?
  • 标题应该是:char + char = int? WAT?
  • byte + byte = int... why?的答案相同

标签: c# .net


【解决方案1】:

根据the documentation of char 可以隐式转换为整数值。 char 类型未定义自定义 operator +,因此使用整数类型。

Eric Lippert 在他的blog entry on "Why does char convert implicitly to ushort but not vice versa?" 中的第一条评论很好地解释了没有隐式转换为字符串的理由:

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

(感谢JimmiTh finding that quote

【讨论】:

  • 根据 Eric Lippert 的说法,只是添加它被设计成这样的原因 - 特别是为什么没有隐式转换为字符串(无论我们是否同意这个基本原理):“它在 v1 中被考虑过.0. 1999 年 6 月 6 日的语言设计说明说:“我们讨论了是否应该存在这种转换,并决定提供第三种方法来进行这种转换是很奇怪的。[语言] 已经支持 c.ToString() 和 new字符串(c)“。'
  • @JimmiTh 非常好!您是否偶然获得了该报价的链接?
  • blogs.msdn.com/b/ericlippert/archive/2009/10/01/… - 这是 Lippert 对第一条评论的回答。
  • @jadarnel27 感谢您的编辑和修复语言。
  • 没问题 =) 我认为您的措辞没有任何问题。我只是想确保 @JimmiTh 的精彩评论能持续下去。
【解决方案2】:

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

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

要做你想做的,从一个空字符串开始:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 是否有任何来源支持这一点?为什么会这样?
    • char 是 unicode 代码点,而不是 ASCII 字符。
    • @Dirk - 我希望我的编辑涵盖你,请在投票前仔细阅读......
    • @Ted A C# char 无法追溯到 ASCII 表,因为该表不代表所有 Unicode 字符。只需在原始答案中将 ASCII 替换为 Unicode 即可。
    • @Ted 我没有投反对票。我刚刚指出,由于 char 是一个 Unicode 代码点,编码为 UTF-16。
    【解决方案4】:

    From the MSDN:

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

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

    'a' 只是数字的简写。

    所以两个字符相加就是一个数字。

    Have a look at this question about adding bytes, it is, although counterintuitive, the same thing.

    【讨论】:

      【解决方案5】:

      规范的另一个相关位,在第 4.1.5 节(整数类型)中将 char 定义为整数类型:

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

      所以对于char,两者都转换为int,然后添加为ints。

      【讨论】:

      【解决方案6】:

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

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

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

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

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

      【讨论】:

        【解决方案7】:

        来自MSDN

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

        char 可以隐式转换为 ushort、int、uint、long、ulong、float、double 或 decimal。因此,赋值操作隐式地将 char 转换为 int。

        【讨论】:

        • 赋值是不是调用隐式转换的。在分配发生时,有一个 int 值等待来自 int + 运算符的结果。
        【解决方案8】:

        charSystem.Char 是一个整数类型:

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

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

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

        【讨论】:

          【解决方案9】:

          如前所述,这是因为 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';
          

          【讨论】:

          • 它的 Unicode 值,而不是 ASCII 码。 C# 不使用 ASCII。
          • @Gorpik 好吧,我的意思是在这种特殊情况下,因为 ASCII 表的 Unicode 值是相同的,不是吗?
          • 是的,它们是,因为 Unicode 旨在保持与 ASCII 的兼容性。但是,既然您可以很容易地说出正确的话,为什么还要说一些巧合和所有可能的char 值的一小部分呢? C# 使用 Unicode,而不是 ASCII。
          【解决方案10】:

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

          【讨论】:

          • 效率在这里无关紧要,决定这一点的是语言的语义。以同样的方式连接像"foo" + "bar" 这样的字符串也是低效的,但这并不能阻止它成为可能,而且没有人会使用一种语言,其设计者决定不使用字符串连接运算符以保护你免受自己的伤害.
          【解决方案11】:

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

          【讨论】:

            【解决方案12】:

            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());
            

            【讨论】:

              【解决方案13】:

              为什么 C# 是这样设计的?不是的默认实现 添加两个字符应该会产生一个连接 字符,而不是 int?

              就你想要完成的事情而言,你的意图是不正确的。 字符串不是字符的添加,字符串是所谓的“单例”字符串的添加。

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

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                • 错了。 short + short 可以超过 short 的值,就像任何其他两个数字类型的总和可以得到一个大于它们的类型可以存储的值一样。在这些情况下,都不会自动扩大执行数字的转换;该值只是溢出并保留最低有效位。相反,这是因为 char 没有定义 + 运算符,但可以隐式转换为的类型 (int) 确实定义了此运算符。
                【解决方案15】:

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

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

                【讨论】:

                  猜你喜欢
                  • 2010-09-30
                  • 2016-09-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-12-10
                  • 2016-07-12
                  • 2018-07-30
                  • 2014-10-07
                  相关资源
                  最近更新 更多