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

问题描述 投票:10回答:3

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

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

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

我很困惑为什么C#会允许这样的东西。在搜索之后,我发现了以下SO问题,Eric Lippert自己回答:Implicit Type cast in C#

摘录:

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

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

char a = 'a';
string z = a; // CS0029 Cannot implicitly convert type 'char' to 'string'

这种转换是我的拙见,非常符合逻辑。它不会导致数据丢失,作者的意图也很清楚。此外,在我阅读charint隐式转换的其余答案之后,我仍然没有看到为什么这不合法的任何理由。

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

C#设计团队有什么理由可以实现从charstring的隐式转换,而它的外观看起来很明显(特别是在将它与charint转换进行比较时)。

c# .net implicit-conversion language-design
3个回答
10
投票

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

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

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

  • 这是拳击转换的一种新形式。 Chars是便宜的价值类型。字符串是堆分配的引用类型。拳击转换可能会导致性能问题并产生收集压力,因此有一种观点认为它们应该在程序中更明显,而不是更明显。
  • 该功能不会被视为“字符可转换为单字符字符串”。用户会将其视为“字符是单字符串”,现在提出许多连锁问题是完全合理的,例如:可以在字母上调用.Length吗?如果我可以将char传递给期望string的方法,并且我可以将字符串传递给期望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> - 只需创建一个返回char的lambda - 和Lazy<char>,以及Nullable<char> - 哦,等等,我们允许转换为Nullable<char>。 :-)

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

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

现在比较这些缺点 - 我相信还有更多我没有列出 - 的好处。好处很小:你可以避免单次调用ToString+ ""或者你做什么来明确地将char转换为字符串。

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

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


2
投票

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

String是一种参考类型。所以它生活在堆上。如果要将值类型用作引用类型,则需要先将其打包。编译器需要确保你知道你正在通过拳击做什么。所以,你不能有一个隐式演员。


0
投票

因为当你向char进行int的演员表时,你不只是改变它的'类型,你在ASCII表中获得它的'索引是一个非常不同的东西,他们不会让你“将一个字符转换为一个int“他们正在为您提供有用的数据以满足可能的需求。

为什么不让char演员到string

因为它们实际上代表了很多不同的东西,并以不同的方式存储。

char和string不是表达同一事物的两种方式。

© www.soinside.com 2019 - 2024. All rights reserved.