我是否应该在 C # 中对不能为负的值使用 uint?

我刚刚尝试实现一个类,其中许多长度/计数属性等是 uint而不是 int。然而,当我这样做的时候,我注意到这样做实际上是很痛苦的,就好像没有人真的想这样做。

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

所以我想知道我是否应该在这里恢复到 int。反正我也不会用全套的。我只是想既然我所处理的仅仅是 不行(如果它是负的,那就是一个错误) ,那么实际使用 uint将是一个不错的主意。

附注: 我看到了 这个问题,这至少解释了为什么框架本身总是使用 int,但即使在自己的代码中,粘贴到 uint实际上也很麻烦,这让我觉得它显然不是真正需要的。

18317 次浏览

While strictly you should use uint for variables that hold non-negative integer you have come across one of reasons why it's not always practicable.

In this case I don't think the reduction in readability that comes with having to do casts is worth it.

My personal feeling is that you should probably just stick to int. It's not worth adding a cast to pretty much every single property access just to reclaim a numeric range that .NET's unlikely to let you use anyway.

A negative value is often used to signal an error condition, and the size of a operation is often returned by a function call; a negative value may therefore signal error without resorting to an exception mechanism.

Also note that .NET often builds upon straight C libraries, therefore it is sensible to continue this convention. If you require a larger index space you can break the convention for different error signalling mechanism.

If you want to check that a value is positive, a better way is probably just by using assert (note this is just a debugging technique - you should ensure that this never occurs in the final code).

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

Using an int is also helpful to detect integer overflow in operations.

I'll add to the other answers also that using uint as type of a public field, property, method, parameter, and so on, is a violation of the Common Language Specification rules and to be avoided when possible.

IMO, the drawback of using uint is that it obscures error conditions. The equivalents of the following code aren't as nice:

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

Of course your programs should not miscalculate anything to begin with, but I feel they also should be written to rapidly detect numerical erros without propagation. In the case where a MaxValue of 2^31 is enough, I say use int along with proper use of System.Diagnostics.Debug.Assert() and corresponding error-checks as exemplified above.

If you do use uint use it along with checked to prevent underflow and get the same results. However I have found that check is a little bit difficult to apply to existing code that uses casts for some purpose.

Don't swim upstream if you don't have to. Not litering your code with casts makes your code more readable. Further, if your possible values fit within an int, then using an int is not a problem.

If you're afraid you might overflow an int, then there by all means.. but don't prematurely optimize.

I would say the improved readability of minimizing casts outweighs the slightly elevated risk of a bug with using int.