9

I came from a mostly C/C++ background before I began using C#. One of the things I did with my first project in C# was make a class like this

class Element{
  public uint Size;
  public ulong BigThing;
}

I was then mortified by the fact that this requires casting:

int x=MyElement.Size;

as does

int x=5;
uint total=MyElement.Size+x;

Why did the language designers decide to make the signed and unsigned integer types not implicitly castable? And why are the unsigned types not used more throughout the .Net library? For instance String.Length can never be negative, yet it is a signed integer.

Earlz
  • 62,085
  • 98
  • 303
  • 499
  • 1
    Even in C++ a cast from unsigned to signed or back causes a warning. – Seva Alekseyev Jul 15 '10 at 20:57
  • @Seva depending on compiler :P.. I realize my first case is a weak one, but my second case is really more what I mean because there is no chance of data loss there unless `x` is negative – Earlz Jul 15 '10 at 21:01
  • On the second count, see my response below... – Seva Alekseyev Jul 15 '10 at 21:06
  • you delete the other question ? anyway the return false; it was the solution :) I check it. – Aristos Jul 16 '10 at 16:06
  • @Aristo yea it was, and it was so obvious I didn't think it really mattered so I deleted it.. I'm under 10k so now I can't even see my deleted question to undelete it. – Earlz Jul 16 '10 at 16:43

5 Answers5

18

Why did the language designers decide to make the signed and unsigned integer types not implicitly castable?

Because that could lose data or throw any exception, neither of which is generally a good thing to allow implicitly. (The implicit conversion from long to double can lose data too, admittedly, but in a different way.)

And why are the unsigned types not used more throughout the .Net library

Unsigned types aren't CLS-compliant - not all .NET languages have always supported them. For example, Visual Basic didn't have "native" support for unsigned data types in .NET 1.0 and 1.1; it was added to the language for 2.0. (You could still use them, but they weren't part of the language itself - you couldn't use the normal arithmetic operators, for example.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

Along with Jon's answer, just because an unsigned number can't be negative doesn't mean it isn't bigger than a signed one. uint is 0 to 4,294,967,295 but int is -2,147,483,648 to 2,147,483,647. Plenty of room above int's max for loss.

Jess
  • 42,368
  • 6
  • 37
  • 51
2

I was then mortified by the fact that this requires casting:

 int x=MyElement.Size;

But you are contradicting yourself here. If you really (really) need Size to be unsigned than assigning it to (signed) x is an error. A deep flaw in your code.

For instance String.Length can never be negative, yet it is a signed integer

But String.IndexOf can return a negative number, and it would be awkward if String.Length and Index values where of different types.

And while in theory there would be merit in an unsigned String.Length (4 GB cap), in practice even the current 2GB is large enough (because strings of that length are rare and unworkable anyway).

So the real answer is: Why use unsigned in the first place?

H H
  • 263,252
  • 30
  • 330
  • 514
  • Well, because it allows a wider expression of unsigned numbers? – Paul Nathan Jul 15 '10 at 21:21
  • @Henk: I think a better example of where using `int` is awkward is `Array.Length`. One would never expect an array to have a negative size, and using a signed type limits the (reported) size of the Array to slightly under 2GB. Also, array indices may never be negative. Now granted, there's the `LongLength` property which reports the array size as an `Int64` - but it still reports it as a signed value. The overriding consideration in these cases is the fact that the designers of .NET chose to make unsigned types non-CLS compliant. Something that's unlikely to ever change at this point. – LBushkin Jul 15 '10 at 21:27
  • @Paul: `decimal` has an even wider range. The question is for _practical_ uses of unsigned. The OP has not provided any. – H H Jul 15 '10 at 21:29
  • @LBushkin: I'm sure I would find an unsigned Length much more awkward. Imagine the spreading out to loop-indices and all sorts of counters. You would end up with unsigned and conversions everywhere. I've seen it in C and C++, don't want to go back (-: – H H Jul 15 '10 at 21:32
  • @Henk: In principle I agree with you that using only signed or only unsigned values in the library does help avoid unecessary (and frustrating) conversions. However, without understanding the underlying reasons (CLS compliance) it may appear that the decision was wrongheaded and arbitrary. That's what I meant when I used the adjective 'awkward'. BTW, it should also be noted that not every expression in C# involving both signed and unsigned types requires conversions - comparisons for instance are generally fine: `int x = 10; uint y = 20; if( x < y ) {...} `. – LBushkin Jul 15 '10 at 21:44
  • @LBushkin: I think that 'CLS compliance' just shifts the question. I assume this kind of issues was considered when that decision was made. – H H Jul 15 '10 at 22:10
1

Because implicitly converting an unsigned integer of 3B into an signed integer is going to blow up.

Unsigned has twice the maximum value of signed. It's the same reason you can't cast a long to an int.

Bobby
  • 11,419
  • 5
  • 44
  • 69
Mike M.
  • 12,343
  • 1
  • 24
  • 28
  • Can someone with enough reputation to edit correct that to say "unsigned integer of 3B into a signed integer?" His intention was clear, just a typo. – Dave McClelland Jul 15 '10 at 21:09
0

On the second count: because they wanted the CLR to be compatible with languages that don't have unsigned datatypes (read: VB.NET).

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • VB.net has had unsigned numbers since at least 2.0. I wasn't aware of them being missing earlier, but that would make a lot of sense -- they weren't in VB in time to make it into the CLS. – cHao Jul 15 '10 at 21:08
  • But changing the String class in .NET v2 (or, for that matter, ever) would break a huge amount of code. – Seva Alekseyev Jul 15 '10 at 21:10