从char隐式转换为单个字符串

时间:2018-09-11 08:55:16

标签: c# .net implicit-conversion language-design

首先:我知道如何解决此问题。我不是在寻找解决方案。我对设计选择背后的原因感兴趣,这些选择导致了一些隐式转换,而没有导致其他转换。

今天,我在代码库中遇到了一个小而有影响力的错误,其中一个int常量是用相同数字的char表示形式初始化的。这导致ASCIIchar的{​​{1}}转换。像这样:

int

我很困惑,为什么C#会允许这样的事情。在四处搜寻之后,我发现了下面的SO问题,其中有Eric Lippert本人的回答:Implicit Type cast in C#

摘录:

  

但是,我们可以对为什么隐式做出有根据的猜测   char-to-ushort被认为是一个好主意。这里的关键思想是   从数字到字符的转换是“可能是狡猾的”   转换。这是您不知道要采取的措施   成为一个角色,并选择将其视为一个角色。好像   您想明确指出自己正在做的事情,   而不是无意间允许它。但是反之则少得多   狡猾。在C程序设计中有悠久的传统   字符作为整数-获取其基础值或   数学。

我可以同意其背后的原因,尽管IDE提示会很棒。但是,我还有另一种情况,即隐式转换突然合法:

char a = 'a';
int z = a;
Console.WriteLine(z);    
// Result: 97

根据我的拙见,这种转换非常合乎逻辑。它不会导致数据丢失,并且作者的意图也很明确。同样,在阅读了char a = 'a'; string z = a; // CS0029 Cannot implicitly convert type 'char' to 'string' char隐式转换的其余答案之后,我仍然看不出任何不合法的理由。

这使我想到了我的实际问题:

C#设计团队有什么理由不执行从intchar的隐式转换,而从外观上看是如此明显(特别是与{ {1}}到string的转换)。

3 个答案:

答案 0 :(得分:10)

首先,正如我经常说的那样,当有人问“为什么不?”时有关C#的问题:设计团队不必提供做功能的理由。功能需要花费时间,精力和金钱,而您执行的每个功能都需要花费时间,精力和金钱才能摆脱更好的功能。

但是我不想单枪匹马地拒绝这个前提。这个问题可能更好地表述为“此提议功能的设计利弊是什么?”

这是一个完全合理的功能,有些语言允许您将单个字符视为字符串。 (Tim在评论中提到了VB,Python还将字符和一个字符的字符串视为可互换的IIRC。我敢肯定还有其他字符。)但是,如果我介绍了此功能,我要指出一些缺点:

  • 这是拳击转换的新形式。字符是便宜的价值类型。字符串是堆分配的引用类型。装箱转换可能会导致性能问题并产生收集压力,因此存在一个论点,即它们应在程序中更可见,而不是不那么可见。
  • 该功能将不会被视为“字符可转换为一个字符的字符串”。用户会认为它是“字符一字符字符串”,现在问很多连锁问题非常合理,例如:可以在字符上调用.Length ?如果我可以将char传递给期望string的方法,并且可以将字符串传递给期望IEnumerable<char>的方法,那么我可以将char传递给期望的方法IEnumerable<char>?好像很奇怪我可以在字符串上调用SelectWhere;我可以喝点酒吗?这似乎更加奇怪。所建议的功能只是提出您的问题;如果实现了它,您现在会问“为什么不能在字符上调用Select?”或类似的东西。

  • 现在将前两点合并在一起。如果我将char视为一个字符的字符串,并将char转换为对象,我会得到装箱的char还是字符串?

  • 我们还可以进一步概括第二点。字符串是字符的集合。如果我们要说一个char可转换为char的集合,那为什么要以字符串停止呢?为什么不还说一个字符也可以用作List<char>?为什么以char结尾?我们是否应该说int可转换为IEnumerable<int>
  • 我们可以进一步推广:如果从char到字符串中的字符序列有明显的转换,那么也有从char到Task<char>的明显转换-只需创建一个完整的返回char并返回Func<char>的任务,只需创建一个返回char并返回Lazy<char>并返回Nullable<char>的lambda哦,等等,我们 do 允许转换为Nullable<char>。 :-)

所有这些问题都是可以解决的,有些语言已经解决了它们。那不是问题。问题是:所有这些问题都是语言设计团队必须识别,讨论和解决的问题。语言设计的基本问题之一是该功能的一般性?在两分钟内,我从“字符可转换为单字符字符串”变为“任何基础类型的值都是可转换为一元类型的等效值”。对于这两个功能以及通用性上的其他各个方面都存在争论。如果您使语言功能过于具体,则会成为大量相互之间无法很好交互的特殊情况。如果您使它们过于笼统,那么,我想您有Haskell。 :-)

假设设计团队对功能进行了总结:所有这些都必须写在设计文档和规范中,并且必须编写代码和测试,哦,我是否提到了每当您更改可转换性规则时,某人的重载解决方案代码就会中断?在第一个版本中,您确实必须正确设置可转换性规则,因为稍后对其进行更改会使现有代码更加脆弱。如果您在版本8中而不是版本1中进行此类更改,则将产生实际的设计成本,并且对实际用户也会产生实际成本。

现在比较这些不利因素-我敢肯定还有更多我没有列出的不利因素。好处很小:您避免一次调用ToString+ ""或进行任何将char显式转换为字符串的操作。

这还远远不够以证明设计,实施,测试和向后兼容的成本是合理的。

就像我说的那样,这是一个合理的功能,并且如果它是该语言的第1版-没有泛型,或者安装了数十亿行代码-那么它会容易得多卖。但是现在,有很多功能具有更大的价值,而价格却更低。

答案 1 :(得分:2)

Char是一种值类型。不,它不是数字int或double,但是它仍然源自System.ValueType。然后,一个char变量存在于堆栈中。

String是引用类型。因此它存在于堆中。如果要将值类型用作引用类型,则需要先将其装箱。编译器需要确保您通过装箱知道自己在做什么。因此,您不能进行隐式强制转换。

答案 2 :(得分:0)

当您将char转换为int时,您不仅改变了它的类型,而且在ASCII表中得到了它的索引,这是完全不同的事情,他们不会让您“将char转换为int”,而是会为您提供有用的数据以满足可能的需求。

为什么不将char强制转换为string

因为它们实际上代表了截然不同的事物,并且以不同的方式存储。

字符和字符串不是表示同一事物的两种方式。