【问题标题】:Why are the unsigned CLR types so difficult to use in C#?为什么无符号 CLR 类型在 C# 中如此难以使用?
【发布时间】:2011-03-16 15:46:48
【问题描述】:

在开始使用 C# 之前,我的背景主要是 C/C++。我在 C# 中的第一个项目中所做的其中一件事就是创建一个这样的类

class Element{
  public uint Size;
  public ulong BigThing;
}

然后我被这需要强制转换的事实感到羞愧:

int x=MyElement.Size;

也一样

int x=5;
uint total=MyElement.Size+x;

为什么语言设计者决定让有符号和无符号整数类型不能隐式转换?为什么在 .Net 库中没有更多地使用无符号类型?例如String.Length 永远不会是负数,但它是一个有符号整数。

【问题讨论】:

  • 即使在 C++ 中,从 unsigned 到 signed 或 back 的强制转换也会导致警告。
  • @Seva 取决于编译器:P.. 我意识到我的第一个案例是一个弱案例,但我的第二个案例确实更符合我的意思,因为除非x,否则那里没有数据丢失的机会是负数
  • 第二次计算,请参阅下面的回复...
  • 你删除了另一个问题?无论如何返回false;这是解决方案:)我检查它。
  • @Aristo 是的,很明显,我认为这并不重要,所以我删除了它。我不到 10k,所以现在我什至看不到我删除的问题取消删除它。

标签: c# .net casting language-design unsigned


【解决方案1】:

为什么语言设计者决定让有符号和无符号整数类型不 隐式可转换?

因为这可能会丢失数据或抛出任何异常,这通常都不是隐式允许的好事情。 (诚​​然,从 long 到 double 的隐式转换也会丢失数据,但方式不同。)

为什么在 .Net 库中没有更多地使用无符号类型

无符号类型不符合 CLS - 并非所有 .NET 语言都一直支持它们。例如,Visual Basic 在 .NET 1.0 和 1.1 中没有对无符号数据类型的“本机”支持。它被添加到 2.0 的语言中。 (你仍然可以使用它们,但它们不是语言本身的一部分——例如,你不能使用普通的算术运算符。)

【讨论】:

  • “虽然我可能是错的” - 你的意思是 .NET 可能是错的?
  • @PostMan:我刚刚发现了更多信息……将编辑。
【解决方案2】:

因为将 3B 的无符号整数隐式转换为有符号整数会爆炸。

无符号的有符号最大值的两倍。这与您不能将 long 转换为 int 的原因相同。

【讨论】:

  • 有足够声誉的人可以编辑纠正说“3B 的无符号整数为有符号整数吗?”他的意图很明确,只是一个错字。
【解决方案3】:

连同乔恩的回答,仅仅因为无符号数不能为负并不意味着它不大于有符号数。 uint 是 0 到 4,294,967,295,但 int 是 -2,147,483,648 到 2,147,483,647。在int 的最大损失之上有足够的空间。

【讨论】:

    【解决方案4】:

    第二点:因为他们希望 CLR 与没有无符号数据类型的语言兼容(阅读:VB.NET)。

    【讨论】:

    • VB.net 至少从 2.0 开始就有无符号数。我之前没有意识到他们失踪了,但这很有意义——他们没有及时进入 VB 以进入 CLS。
    • 但是在 .NET v2 中更改 String 类(或者,就此而言,永远)会破坏大量代码。
    【解决方案5】:

    然后我被这需要强制转换的事实感到羞愧:

     int x=MyElement.Size;
    

    但你在这里自相矛盾。如果你真的(真的)需要 Size 是无符号的,而不是将它分配给(有符号的) x 是一个错误。您的代码中存在严重缺陷。

    例如 String.Length 永远不能是负数,但它是一个有符号整数

    但是 String.IndexOf 可以返回一个负数,如果 String.Length 和 Index 的值是不同的类型会很尴尬。

    虽然理论上无符号 String.Length(上限为 4 GB)是有好处的,但实际上即使是当前的 2GB 也足够大(因为这种长度的字符串很少见且无论如何都不可行)。

    所以真正的答案是:为什么首先使用无符号?

    【讨论】:

    • 好吧,因为它允许更广泛地表达无符号数?
    • @Henk:我认为使用int 很尴尬的一个更好的例子是Array.Length。人们永远不会期望数组具有负大小,并且使用有符号类型将数组的(报告的)大小限制为略低于 2GB。此外,数组索引可能永远不会是负数。现在被授予,LongLength 属性将数组大小报告为Int64 - 但它仍将其报告为有符号值。在这些情况下,最重要的考虑是 .NET 的设计者选择使无符号类型不符合 CLS 的事实。在这一点上不太可能改变的东西。
    • @Paul:decimal 的范围更广。问题是关于无符号的实际使用。 OP 没有提供任何内容。
    • @LBushkin:我确信我会发现 unsigned Length 更加尴尬。想象一下扩展到循环索引和各种计数器。你最终会到处都是无符号和转换。我在 C 和 C++ 中看到过,不想回去(-:
    • @Henk:原则上我同意你的观点,在库中只使用有符号或无符号值确实有助于避免不必要的(和令人沮丧的)转换。但是,如果不了解根本原因(CLS 合规性),该决定可能看起来是错误的和武断的。这就是我使用形容词“尴尬”时的意思。顺便说一句,还应该注意的是,并非 C# 中涉及有符号和无符号类型的每个表达式都需要转换 - 例如比较通常很好:int x = 10; uint y = 20; if( x < y ) {...}
    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 2017-09-14
    • 1970-01-01
    • 2014-02-06
    • 1970-01-01
    • 2019-01-09
    相关资源
    最近更新 更多