当然,我知道无符号整数(uint
)和有符号整数(int
)之间的基本区别。
我注意到在.NET公共类中,名为Length
的属性总是使用有符号整数。
可能这是因为无符号整数不符合CLS。
然而,例如,在我的静态函数中:
public static double GetDistributionDispersion(int tokens, int[] positions)
参数tokens
和positions
中的所有元素都不能为负数。如果它是否定的,最终结果是无用的。因此,如果我int
和tokens
同时使用positions
,我必须在每次调用此函数时检查值(如果找到负值,则返回非感知值或抛出异常? ??),这很乏味。
好的,那么我们应该对这两个参数使用uint
。这对我来说真的很有意义。
int
。这是否意味着在他们的实现中,他们总是检查每个值的负面(如果它应该是非负的)?
所以,总之,我该怎么办?
我可以提供两种情况:
我们应该为这两种情况使用不同的方案吗?
彼得
P.S。:我做了很多研究,仍然没有理由说服我不要使用uint
: - )
答案 0 :(得分:5)
我看到三个选项。
使用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
,则该信息有效。
您有理由要求您的域名中包含非负面消息。它正在建模一些概念。不妨将这个概念推广到域模型中的真实对象,并封装随附的所有概念。
答案 1 :(得分:3)
我使用 uint 。
是的,其他答案都是正确的...但我更喜欢 uint ,原因之一是:
让界面更加清除。如果参数(或返回值)是无符号的,那是因为它不能为负数(您是否看到了负集合计数?)。否则,我需要检查不能为负的参数,文档参数(和返回值);然后我需要编写额外的单元测试来检查参数和返回的值(哇,有人会抱怨做演员表演吗?int casts如此频繁?不,根据我的经验)。
此外,用户需要测试返回值否定性,这可能更糟。
我不介意CLS complia,所以为什么我应该?从我的观点来看,问题应该颠倒过来:当价值不能为负时,我为什么要使用整数?
对于附加信息(错误,例如......)返回负值的观点:我不喜欢 C-ish 设计。我认为可能有更现代的设计来实现这一点(即使用异常,或者交替使用out值和布尔返回值)。
答案 2 :(得分:2)
是的,去int。我曾经尝试过自己只是为了在我的lib中有一些讨厌的演员时再次重构一切。 我认为选择int的决定是出于历史原因,通常结果为-1表示存在某种错误(例如在IndexOf中)。
答案 3 :(得分:1)
int值。当您需要在不久的将来进行API更改时,它提供了更大的灵活性。 例如,python通常使用负索引来表示从字符串末尾反向计数。
当溢出时,值也会变为负值,断言会捕获它。
它是速度与稳健性的折衷。
答案 4 :(得分:1)
正如您所读到的那样违反了公共语言规范规则,但随后会使用该函数的频率如何,并且如果它将使用其他方法进行处理,那么它们通常需要int
作为参数让你陷入铸造价值的麻烦。
如果你打算把它作为一个库提供,那么它更好地坚持传统的int,你需要隐含地处理你可能没有获得正值的条件,这意味着在页面上乱扔乱码。< / p>