Use uint or int
本文关键字:int or uint Use | 更新日期: 2023-09-27 18:09:33
当然,我知道无符号整数(uint
)和有符号整数(int
)之间的基本区别。
我注意到在。net公共类中,一个名为Length
的属性总是使用有符号整数。
可能这是因为无符号整数不符合CLS。
但是,例如,在我的静态函数中:public static double GetDistributionDispersion(int tokens, int[] positions)
参数tokens
和positions
中的所有元素不能为负。如果它是负的,最后的结果是无用的。因此,如果我对tokens
和positions
都使用int
,我必须在每次调用该函数时检查值(如果发现负值,则返回无意义值或抛出异常??),这是乏味的。
OK,那么我们应该对两个参数都使用uint
。这对我来说真的很有意义。
我发现,然而,在许多公共api中,他们几乎总是使用int
。这是否意味着在它们的实现中,它们总是检查每个值的负性(如果它应该是非负的)?
总之,我该怎么办?
可以提供两种情况:
- 这个函数只能在我自己的解决方案中调用;
- 此函数将被其他团队中的其他人用作库。
我们是否应该对这两种情况使用不同的方案?
彼得注::我确实做了很多研究,仍然没有理由说服我不要使用uint
:-)
我看到三个选项
使用uint
。这个框架没有,因为它不兼容CLS。但是你一定要符合CLS吗?(也有一些不好玩的算术问题;扔得到处都是一点都不好玩。由于这个原因,我倾向于取消uint
)。
使用int
但是使用契约:
Contract.Requires(tokens >= 0);
Contract.Requires(Contract.ForAll(positions, position => position >= 0));
明确你所需要的。
创建一个封装需求的自定义类型:
struct Foo {
public readonly int foo;
public Foo(int foo) {
Contract.Requires(foo >= 0);
this.foo = foo;
}
public static implicit operator int(Foo foo) {
return this.foo;
}
public static explicit operator Foo(int foo) {
return new Foo(foo);
}
}
:
public static double GetDistributionDispersion(Foo tokens, Foo[] positions) { }
啊,不错。在我们的方法中不需要担心它。如果我们得到一个Foo
,它是有效的。
你有理由在你的领域中要求非否定性。这是对一些概念的建模。不妨将该概念提升为域模型中的真实对象,并封装与之相关的所有概念。
我使用 int
是的,其他答案都是正确的…但是我更喜欢 int,原因只有一个:
Make interface more clear。如果参数(或返回值)是无符号的,那是因为它不能是负的(您见过负的集合计数吗?)否则,我需要检查参数,文档参数(和返回值)不能为负;然后我需要编写额外的单元测试来检查参数和返回值(哇,有人会抱怨进行强制类型转换吗?int类型转换如此频繁吗?不,根据我的经验)。
另外,用户需要测试返回值的否定性,这可能会更糟。
我不介意CLS的兼容性,为什么我要介意呢?从我的角度来看,问题应该反过来:当value不能为负时,为什么我要使用int ?
对于附加信息返回负值(例如错误…)的点:I don't like so C-ish design。我认为可能有一个更现代的设计来完成这一点(即使用异常,或替代使用out值和布尔返回值)。
选择int。我曾经试图让自己去重构所有的东西,只要我在我的库中有了令人讨厌的强制类型转换。我猜使用int的决定是出于历史原因,通常-1的结果表示某种错误(例如在IndexOf中)。
int。当您在不久的将来需要更改API时,它提供了更大的灵活性。例如,python经常使用负索引来表示从字符串末尾开始的反向计数。
值在溢出时也变为负值,断言将捕获它。
当你阅读时,它违反了公共语言规范规则,但是该函数使用的频率如何,如果它将与其他方法结合在一起,他们通常期望int
作为参数,这将使你陷入转换值的麻烦。
如果你打算让它作为库可用,那么最好坚持传统的int,否则你需要隐式地处理可能无法得到正值的情况,这意味着在页面上乱扔检查。
趣味阅读- SO链接