为什么 Stream.Write 不接受 UInt?
Why does Stream.Write not take a UInt?
对我来说,Stream.Write 使用 int
而不是 UInt
似乎非常不合逻辑...对于这个事实,除了 "legacy" 代码之外还有其他解释吗?有人想写 -1
字节吗?!?
无符号类型不符合 CLS,因此 Stream.Write
不使用 uint
进行偏移和计数。
The uint type is not CLS-compliant. Use int whenever possible.
有一篇旧文章:Why we don't have unsigned types in the CLS by Brad Abrams (2 Sep 2003)解释了原因:
However there is one issue that keeps coming up: Why did we not allow
unsigned types (UInt32 and the like) in the CLS?
Well, there are really two answers to this question. At the first
level some languages (such as VB.NET) do not offer full support for
unsigned types. For example you can’t have unsigned literals in
VB.NET…. But to be fair that is not a completely satisfying answer
because when we started the CLS you could not subclass in VB.NET
either, but we extended that language to support what we knew people
would want. We could have done the same thing with unsigned types.
But we didn’t. Why not? Well, that gets a deeper reason. In fact
the same reason why early betas of the C# language did not support
unsigned types (no ushort, uint and the like).
The general feeling
among many of us is that the vast majority of programming is done
with signed types. Whenever you switch to unsigned types you force a
mental model switch (and an ugly cast). In the worst cast you build
up a whole parallel world of APIs that take unsigned types. The value
of avoiding the “< 0” check is not worth the inclusion of generics in
the CLS.
(请注意 VB.Net 的较新版本(VB 8 之后)支持无符号类型)。
还有一点要补充 (可能无关),Stream.Write
implementation 检查负值:
[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"));
The uint type is not CLS-compliant. Use int whenever possible.
所以 Stream.Write
使用 int 进行偏移和计数。
reasons given by ShuggyCoUk更清楚:
- uint is not CLS compliant, thus making a built in type (array) dependent on it would have been problematic
- The runtime as
originally designed prohibits any object on the heap occupying more
than 2GB of memory. Since the maximum sized array that would less than
or equal to this limit would be new byte[int.MaxValue] it would be
puzzling to people to be able to generate positive but illegal array
lengths.
- Note that this limitation has been somewhat removed in the 4.5 release,
though the standard Length as int remains.
- Historically C# inherits
much of its syntax and convention from C and C++. In those arrays are
simply pointer arithmetic so negative array indexing was possible
(though normally illegal and dangerous). Since much existing code
assumes that the array index is negative this would have been a factor
- On a related note the use of signed integers for array indexes in C/C++ means that interop with these languages and unmanaged functions
would require the use of ints in those circumstances anyway, which may
confuse due to the inconsistency.
- The BinarySearch implementation
(a very useful component of many algorithms) relies on being able to
use the negative range of the int to indicate that the value was not
found and the location at which such a value should be inserted to
maintain sorting.
- When operating on an array it is likely that you
would want to take a negative offset of an existing index. If you used
an offset which would take you past the start of the array using unit
then the wrap around behaviour would make your index possibly legal
(in that it is positive). With an int the result would be illegal (but
safe since the runtime would guard against reading invalid memory)
信不信由你,无符号整数是 not part of the Common Language Specification (CLS)。
The uint type is not CLS-compliant. Use int whenever possible.
因此,为了符合 CLS,Microsoft 在此处使用 int
而不是 uint
。
对我来说,Stream.Write 使用 int
而不是 UInt
似乎非常不合逻辑...对于这个事实,除了 "legacy" 代码之外还有其他解释吗?有人想写 -1
字节吗?!?
无符号类型不符合 CLS,因此 Stream.Write
不使用 uint
进行偏移和计数。
The uint type is not CLS-compliant. Use int whenever possible.
有一篇旧文章:Why we don't have unsigned types in the CLS by Brad Abrams (2 Sep 2003)解释了原因:
However there is one issue that keeps coming up: Why did we not allow unsigned types (UInt32 and the like) in the CLS?
Well, there are really two answers to this question. At the first level some languages (such as VB.NET) do not offer full support for unsigned types. For example you can’t have unsigned literals in VB.NET…. But to be fair that is not a completely satisfying answer because when we started the CLS you could not subclass in VB.NET either, but we extended that language to support what we knew people would want. We could have done the same thing with unsigned types. But we didn’t. Why not? Well, that gets a deeper reason. In fact the same reason why early betas of the C# language did not support unsigned types (no ushort, uint and the like).
The general feeling among many of us is that the vast majority of programming is done with signed types. Whenever you switch to unsigned types you force a mental model switch (and an ugly cast). In the worst cast you build up a whole parallel world of APIs that take unsigned types. The value of avoiding the “< 0” check is not worth the inclusion of generics in the CLS.
(请注意 VB.Net 的较新版本(VB 8 之后)支持无符号类型)。
还有一点要补充 (可能无关),Stream.Write
implementation 检查负值:
[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"));
The uint type is not CLS-compliant. Use int whenever possible.
所以 Stream.Write
使用 int 进行偏移和计数。
reasons given by ShuggyCoUk更清楚:
- uint is not CLS compliant, thus making a built in type (array) dependent on it would have been problematic
- The runtime as originally designed prohibits any object on the heap occupying more than 2GB of memory. Since the maximum sized array that would less than or equal to this limit would be new byte[int.MaxValue] it would be puzzling to people to be able to generate positive but illegal array lengths.
- Note that this limitation has been somewhat removed in the 4.5 release, though the standard Length as int remains.
- Historically C# inherits much of its syntax and convention from C and C++. In those arrays are simply pointer arithmetic so negative array indexing was possible (though normally illegal and dangerous). Since much existing code assumes that the array index is negative this would have been a factor
- On a related note the use of signed integers for array indexes in C/C++ means that interop with these languages and unmanaged functions would require the use of ints in those circumstances anyway, which may confuse due to the inconsistency.
- The BinarySearch implementation (a very useful component of many algorithms) relies on being able to use the negative range of the int to indicate that the value was not found and the location at which such a value should be inserted to maintain sorting.
- When operating on an array it is likely that you would want to take a negative offset of an existing index. If you used an offset which would take you past the start of the array using unit then the wrap around behaviour would make your index possibly legal (in that it is positive). With an int the result would be illegal (but safe since the runtime would guard against reading invalid memory)
信不信由你,无符号整数是 not part of the Common Language Specification (CLS)。
The uint type is not CLS-compliant. Use int whenever possible.
因此,为了符合 CLS,Microsoft 在此处使用 int
而不是 uint
。