53

Possible Duplicates:
Why does .NET use int instead of uint in certain classes?
Why is Array.Length an int, and not an uint

I've always wonder why .Count isn't an unsigned integer instead of a signed one?

For example, take ListView.SelectedItems.Count. The number of elements can't be less then 0, so why is it a signed int?

If I try to test if there are elements selected, I would like to test

 if (ListView.SelectedItems.Count == 0) {}

but because it's a signed integer, I have to test

 if (ListView.SelectedItems.Count <= 0) {}

or is there any case when .Count could be < 0 ?

Community
  • 1
  • 1
Inno
  • 2,567
  • 5
  • 32
  • 44
  • 4
    I guess it's from convenience, because you can't cast a uint to an int and most people are used to using ints for indexers... – Martin Hennings Sep 07 '10 at 12:19
  • 3
    you can still test `== 0`, though, right? since, as you point out, it'll never be less than 0. after all, there's no escaping that, at some point, your code will make some basic assumption that other people's code will behave in the way that the member names imply. i'd say that grants you the ability to assume `Count` will never be less than 0, and check for equality. – David Hedlund Sep 07 '10 at 12:23
  • And duplicate of [Why is Array.Length an int, and not an uint](http://stackoverflow.com/questions/6301) , [Why aren't unsigned variables used more often?](http://stackoverflow.com/questions/490222) – H H Sep 07 '10 at 16:03

5 Answers5

60

Unsigned integer is not CLS-compliant (Common Language Specification)

For more info on CLS compliant code, see this link:

http://msdn.microsoft.com/en-us/library/bhc3fa7f.aspx

Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
  • 15
    Although this answers the question to the letter, it doesn’t explain. Perhaps the question should rather have been, “*why* isn’t it CLS compliant?” That was indeed a weird decision. – Konrad Rudolph Sep 07 '10 at 12:24
  • 14
    The question why uint is not CLS-compliant is a topic for a separate question, which has already been asked here: http://stackoverflow.com/questions/6325/why-are-unsigned-ints-not-cls-compliant – Philippe Leybaert Sep 07 '10 at 12:27
7

Mabye because the uint data type is not part of the CLS (common language specification) as not all .Net languages support it.

Here is very similar thread about arrays:

Why is Array.Length an int, and not an uint

Community
  • 1
  • 1
nan
  • 19,595
  • 7
  • 48
  • 80
5

Let’s look at this from a practical angle.

For better or worse, signed ints are the normal sort of ints in use in .NET. It was also normal to use signed ints in C and C++. So, most variables are declared to be int rather than unsigned int unless there is a good reason otherwise.

Converting between an unsigned int and a signed int has issues and is not always safe.

On a 32 bit system it is not possible for a collection to have anywhere close to 2^^32 items in it, so a signed int is big enough in all cases.

On a 64 bit system, an unsigned int does not gain you much, in most cases a signed int is still big enough, otherwise you need to use a 64 bit int. (I expect that none of the standard collection will cope well with anywhere near 2^^31 items on a 64 system!)

Therefore given that using an unsigned int has no clear advantage, why would you use an unsigned int?

Tim S. Van Haren
  • 8,861
  • 2
  • 30
  • 34
Ian Ringrose
  • 51,220
  • 55
  • 213
  • 317
  • 6
    I see a clear advantage: when somebody makes a mistake, e.g. `(Names.Count < 0)` (instead of `(Names.Count > 0)`) the compiler can warn. I think warning users for making mistakes is a very important task of the compiler, and any language that makes it easier to detect mistakes has an advantage over competitors. In fact, that is why I prefer compiled languages in the first place. – Johan Aug 22 '17 at 07:14
  • 2
    This explanation doesn't hold water. You cannot have have a negative number of items in a list / dictionary / etc, so making Count be an int is silly. – antred Jan 28 '19 at 12:45
5
  1. It's not CLS compliant, largely to allow wider support from different languages.

  2. A signed int offers ease in porting code from C or C++ that uses pointer arithmetic.

  3. Count can be part of an expression where the overall value can be negative. In particular, count has a direct relationship to indices, where valid indices are always in the range [0, Count - 1], but negative results are used e.g. by some binary search methods (including those provided by the BCL) to reflect the position where a new item should be inserted to maintain order.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
0

In vb.net, the normal looping construct (a "For/Next loop") will execute the loop with values up to and including the maximum value specified, unlike C which can easily loop with values below the upper limit. Thus, it is often necessary to specify a loop as e.g. "For I=0 To Array.Length-1"; if Array.Length were unsigned and and zero, that could cause an obvious problem. Even in C, one benefits from being able to say "for (i=Array.Length-1; i GE 0; --i)". Sometimes I think it would be useful to have a 31-bit integer type which would support widening casts to both signed and unsigned int, but I've never heard of a language supporting such.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Exactly !! VB is different : In VB, the term true is 0 and the term false is -1. With this axiom, -1 is an int and cannot be said with an unsigned int. It's clearly a CPU optimization problem – user1587368 Jan 03 '17 at 01:07
  • Exactly !! VB is different : In VB, the term true is 0 and the term false is -1. With this axiom, -1 is an int and cannot be said with an unsigned int. I think the reason of using a signed version of an integer, instead of an unsigned int is clearly a CPU optimization problem: a number with zero has a negative value -1. For example, a NOT door in a logical scheme is efficient on how to say that a value is equals to zero or is empty. – user1587368 Jan 03 '17 at 01:22
  • @user1587368: An advantage of (two's-complement) signed int is that such types have -1 as the "all-bits-set" value, regardless of size, whereas every size of unsigned type has a different "all-bits-set" value. – supercat Jan 03 '17 at 15:25