我应该在C#中将uint用作不能为负的值吗?


79

我刚刚尝试实现一个类,其中使用许多length / count属性等uint代替int。但是,在这样做的同时,我注意到这样做实际上是很痛苦的,就像没有人真正想要这样做那样。

几乎所有提供整数类型的东西都返回int,因此需要在多个点上进行强制转换。我想构造一个StringBuffer缓冲区长度默认为该类中字段之一的。也需要强制转换。

所以我想知道我是否应该回到int这里。无论如何,我当然不会使用整个范围。我只是认为,因为我在那里处理的东西不可能完全是负面的(如果是的话,那将是一个错误),所以实际使用它是一个好主意uint

PS:我看到了这个问题,这至少可以解释为什么框架本身总是使用,int但是即使在自己的代码中,遵守它实际上也很麻烦,uint这使我认为显然并不需要它。


Answers:


42

虽然严格来说,您应该将uint变量用于包含非负整数的变量,但您却发现它并非总是可行的原因之一。

在这种情况下,我认为必须进行强制转换会导致可读性的降低是不值得的。


2
很难说,我认为强制转换仅会降低索引器的可读性,而您可以创建包装器。变成负数的整数是痛苦且昂贵的错误。
user1496062

6
如果你需要创建一个包装为一个整数,那么你有一个以上的可读性问题:)
秒。

61

我还将在其他答案中添加使用uint作为公共字段,属性,方法,参数等的类型,这违反了公共语言规范规则,应尽可能避免使用。


3
后来,我被微软严格烧死了。事实证明,IntPtr应该具有uint构造函数。
约书亚

3
如果他们支持自然数,我也要补充一点,例如,此类型的值是0到6,它们可以消除所有数组边界检查,从而将性能提高5-10%。
user1496062

利珀特先生,您是否同意上述说法?
AgentFire '19

@AgentFire:该声明声称,如果有人做了某件事,那将导致特定的性能改进。我没有能力评估反事实主张;如果您想知道该声明是否成立,请询问user1496062是什么根据来证明他们的主张,而不是我?我不是提出不支持的主张的人。
埃里克·利珀特

1
@EricLippert是您最短的最长的“我不知道”的时间,不是

4

负值通常用于表示错误情况,并且操作的大小通常由函数调用返回;因此,如果不使用异常机制,则负值可能表示错误。

还请注意,.NET通常建立在直接的C库上,因此继续使用此约定是明智的。如果您需要更大的索引空间,则可以打破不同错误信号传递机制的约定。


24
.NET与抛出异常而不是返回错误代码非常一致。-1返回在托管代码中并不常见。
克里斯(ChrisV)2010年

同意,但是我们谈论的是一种在Windows技术中普遍存在的设计约定(除了支持它们的例外情况)-.NET库中与低级代码交互的部分必须在CRT错误代码和例外之间进行转换-为什么他们提出int而不是uint的约定是可以理解的。
哈桑·赛义德

@HassanSyed仍然,如果某些winapi返回负值,框架仍将抛出它自己的异常,将所有内容包装到一个整洁的shell中,因此该参数在这里并不适用。
AgentFire '19

3

我个人的感觉是,您应该只坚持int。仅仅为了收回.NET不太可能让您使用的数值范围,几乎不应该在每个属性访问中添加强制类型转换。


3

使用int还有助于检测操作中的整数溢出。


如果它溢出到零,则不是100%准确。同样,默认情况下启用了溢出保护。
AgentFire '19

3

IMO,使用的缺点uint是它掩盖了错误条件。以下代码的等效项不是很好:

if (len < 0)
    terminate_program("length attained impossible value.");

当然,您的程序一开始就不会误算任何东西,但我认为它们也应该编写为快速检测数值错误而不会传播。在MaxValue为2 ^ 31的情况下,我说的是useint以及System.Diagnostics.Debug.Assert()上面所举例说明的正确使用和相应的错误检查。

如果您确实使用uint它,请与一起使用checked以防止下溢并获得相同的结果。但是我发现,将检查应用到出于某种目的而使用强制类型转换的现有代码有些困难。


2

如果不需要,不要上游游泳。不使用强制转换对代码进行编码会使代码更具可读性。此外,如果您的可能值适合int以内,那么使用int也不成问题。

如果您担心自己可能会溢出一个int,则一定要在其中进行..但不要过早地进行优化。

我要说的是,最小化强制类型转换所带来的更好的可读性胜过使用int带来的Bug风险略有提高。


2

如果要检查值是否为正,则更好的方法可能是使用assert(注意,这只是一种调试技术-您应确保在最终代码中永远不会发生这种情况)。

using System.Diagnostics;
...
Debug.Assert (i > 0);

1
另请参阅ArgumentOutOfRangeException
弗雷德(Fred)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.