从char到单个字符串的隐式转换

pyr*_*lus 10 .net c# language-design implicit-conversion

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

今天我在代码库中遇到了一个小但有影响的错误,其中一个int常量用char相同数字的表示初始化.这导致ASCII转换char为a int.像这样的东西:

char a = 'a';
int z = a;
Console.WriteLine(z);    
// Result: 97
Run Code Online (Sandbox Code Playgroud)

我很困惑为什么C#会允许这样的东西.搜索后我发现以下SO问题,Eric Lippert自己给出了答案:C#中的隐式类型转换

摘录:

但是,我们可以做出有根据的猜测,为什么隐含的char-to-ushort被认为是个好主意.这里的关键思想是从数字到字符的转换是"可能是狡猾的"转换.它正在采取你不知道的东西是一个角色,并选择将其视为一个角色.这似乎是你想要明确表达的事情,而不是意外地允许它.但反之则不那么狡猾.C编程中有一个悠久的传统,即将字符视为整数 - 获取它们的基础值,或者对它们进行数学处理.

我同意它背后的推理,虽然IDE提示会很棒.但是,我有另一种情况,隐式转换突然合法:

char a = 'a';
string z = a; // CS0029 Cannot implicitly convert type 'char' to 'string'
Run Code Online (Sandbox Code Playgroud)

这种转换是我的拙见,非常符合逻辑.它不会导致数据丢失,作者的意图也很清楚.还后,我读了答案的其余部分char,以int隐式转换,我还没有看到任何理由,这不应该是合法的.

这就引出了我的实际问题:

C#设计团队有什么理由可以实现隐式转换char为a string,而它看起来很明显(特别是在将它charint转换进行比较时).

Eri*_*ert 10

首先,正如我总是说有人问"为什么不呢?" 关于C#的问题:设计团队没有提供一个理由,不是做一个功能.具有成本时间,精力和金钱,而且您所做的每项功能都需要时间,精力和金钱,而不是更好的功能.

但我不想只是拒绝这个前提; 问题可能更好地表达为"这个拟议特征的设计优缺点是什么?"

这是一个完全合理的功能,有些语言允许您将单个字符视为字符串.(Tim在评论中提到了VB,而且Python也将字符和单字符字符串视为可互换的IIRC.我确信还有其他字符串.)但是,如果我提出这个功能,我会指出一些缺点:

  • 这是拳击转换的一种新形式.Chars是便宜的价值类型.字符串是堆分配的引用类型.拳击转换可能会导致性能问题并产生收集压力,因此有一种观点认为它们应该在程序中更明显,而不是更明显.
  • 该功能不会被视为"字符可转换为单字符字符串".用户会将其视为"字符单字符串",现在提出许多连锁问题是完全合理的,例如:可以调用.Length字符吗?如果我可以将char传递给期望a的方法string,并且我可以将字符串传递给期望的方法,我可以将a IEnumerable<char>传递char给期望的方法IEnumerable<char>吗?这似乎......很奇怪.我可以打电话SelectWhere在一个字符串; 我可以上char吗?这似乎更奇怪.所有提议的功能都是移动您的问题 ; 如果它被实现了,你现在要问"为什么我不能在Char上调用Select?" 或某些这样的事情.

  • 现在将前两点结合起来.如果我将chars视为单字符字符串,并将char转换为对象,我会获得盒装字符或字符串吗?

  • 我们还可以进一步概括第二点.字符串是字符的集合.如果我们要说一个字符可以转换成一个字符集,为什么要用字符串停止?为什么不说一个字符也可以用作List<char>?为什么要停下来char?我们应该说一个int可兑换成IEnumerable<int>
  • 我们可以进一步概括:如果有一个明显的从char转换为chars-in-a-string的转换,那么还有一个明显的从char转换到Task<char>- 只需创建一个返回char的完成任务 - 和到Func<char>-只需创建一个返回字符拉姆达-并Lazy<char>,并Nullable<char>-哦,等等,我们允许转换Nullable<char>.:-)

所有这些问题都是可以解决的,有些语言已经解决了.那不是问题.问题是:所有这些问题都是语言设计团队必须识别,讨论和解决的问题.语言设计的一个基本问题是这个功能应该如何通用? 在两分钟内,我已经从"字符可转换为单字符字符串"变为"基础类型的任何值可转换为monadic类型的等效值".对于这两个特征以及关于通用性的各种其他观点,都有一个论点.如果您使语言功能过于具体,则会成为大量特殊情况,彼此之间的互动性很差.如果你使它们太笼统,那么,我猜你有Haskell.:-)

假设设计团队得出关于该特性的结论:所有这些都必须写在设计文档和规范中,代码和测试必须写入,哦,我是否在任何时候提到对可兑换规则进行更改,某人的重载解析代码中断了吗?您必须在第一个版本中获得正确的可转换性规则,因为稍后更改它们会使现有代码更加脆弱.有实际的设计成本,如果您在版本8而不是版本1中进行此类更改,则实际用户会有实际成本.

现在比较这些缺点 - 我相信还有更多我没有列出 - 的好处.有利的一面是相当微小的:你避免单个呼叫ToString+ ""或任何你做一个字符转换为字符串明确.

这甚至不足以证明设计,实施,测试和向后兼顾成本的合理性.

就像我说的那样,它是一个合理的功能,并且它已经使用了该语言的第1版 - 它没有泛型,或者已经安装了数十亿行代码 - 那么它本来就更容易销售.但是现在,有很多功能对于小型降压有更大的影响.

  • 哇,谢谢你这么详细的回答。我希望它会被你回答,我只是没想到它真的发生了 ;-) 我想我会错过很多东西,最重要的是概括。我也考虑过性能,但我倒退了。这不是您想要避免的性能成本,而是您看不到成本的事实。您的回答最有帮助,可惜我只能投票并标记一次。谢谢! (2认同)