对我来说Stream.Write使用int
,而不是...对我来说似乎非常不合逻辑UInt
。对于这个事实,除了“遗留”代码之外还有其他解释吗?有人想写-1
字节吗?!?
3 回答
无符号类型不符合 CLS,因此Stream.Write
不uint
用于偏移和计数。
请参阅:uint(C# 参考)
uint 类型不符合 CLS。尽可能使用 int。
有一篇旧文章: Brad Abrams ( 2003 年 9 月 2 日)在 CLS 中为什么没有无符号类型解释了原因:
然而,有一个问题不断出现:为什么我们不允许在 CLS 中使用无符号类型(UInt32 等)?
嗯,这个问题真的有两个答案。 在第一层,一些语言(例如 VB.NET)不提供对无符号类型的完全支持。 例如,您不能在 VB.NET 中使用无符号文字……。但公平地说,这并不是一个完全令人满意的答案,因为当我们启动 CLS 时,您也不能在 VB.NET 中进行子类化,但我们扩展了该语言以支持我们知道人们想要的东西。我们可以对无符号类型做同样的事情。但我们没有。为什么不?嗯,这有更深层次的原因。事实上,与早期 C# 语言的 beta 版本不支持无符号类型(没有 ushort、uint 等)的原因相同。
我们许多人的普遍感觉是,绝大多数编程都是使用有符号类型完成的。每当您切换到无符号类型时,您都会强制转换心智模型(以及丑陋的演员表)。 在最糟糕的情况下,您构建了一个采用无符号类型的 API 的整个并行世界。避免“< 0”检查不值得在 CLS 中包含泛型。
(请注意,较新版本的 VB.Net(VB 8 以上)支持无符号类型)。
要添加的另一件事(可能不相关),Stream.Write
实现检查负值:
[System.Security.SecuritySafeCritical] // auto-generated
public override void Write(byte[] array, int offset, int count) {
if (array==null)
throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
if (array.Length - offset < count)
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
仅来自uint MSDN
uint 类型不符合 CLS。尽可能使用 int。
因此Stream.Write
使用 int 进行偏移和计数。
ShuggyCoUk给出的理由更清楚了:
- uint 不符合 CLS,因此依赖于它的内置类型(数组)将是有问题的
- 最初设计的运行时禁止堆上的任何对象占用超过 2GB 的内存。由于小于或等于此限制的最大数组将是 new byte[int.MaxValue] ,因此能够生成正数但非法的数组长度会让人们感到困惑。
- 请注意,尽管标准 Length as int 仍然存在,但在 4.5 版本中已消除了此限制。
- 从历史上看,C# 继承了 C 和 C++ 的大部分语法和约定。在这些数组中只是简单的指针运算,因此负数组索引是可能的(尽管通常是非法和危险的)。由于许多现有代码假定数组索引为负,这将是一个因素
- 在相关说明中,在 C/C++ 中将有符号整数用于数组索引意味着与这些语言和非托管函数的互操作无论如何都需要在这些情况下使用 int,这可能会由于不一致而造成混淆。
- BinarySearch 实现(许多算法中非常有用的组件)依赖于能够使用 int 的负值范围来指示未找到该值以及应插入此类值以保持排序的位置。
- 在对数组进行操作时,您可能希望对现有索引进行负偏移。如果您使用了一个偏移量,它将使您使用 unit 超出数组的开头,那么环绕行为将使您的索引可能合法(因为它是正数)。使用 int 结果将是非法的(但安全,因为运行时会防止读取无效内存)