Reputation: 585
How to cast some negative number to unsigned types
.
Type type = typeof (ushort);
short num = -100;
ushort num1 = unchecked ((ushort) num); //When type is known. Result 65436
ushort num2 = unchecked(Convert.ChangeType(num, type)); //Need here the same value
Upvotes: 6
Views: 17148
Reputation: 1440
If you're fine using unsafe
code you could always write a function like this and do the conversion using pointers:
public static unsafe TTo Convert<TFrom, TTo>(TFrom value) where TFrom : unmanaged where TTo : unmanaged
{
if (sizeof(TFrom) != sizeof(TTo))
{
throw new ArgumentException("Source and target types must be the same size!");
}
return *(TTo*)&value;
}
which you'd use like this:
short num = -100;
ushort uNum = Convert<short, ushort>(num);
The benefits here being no boxing, no type checking, allocation free code and if you're bold and know what you're doing you could even remove the size checking to get a branch-less implementation.
Obvious drawbacks here are the unsafe
keyword which often is a no-go in many business applications and the generic implementation would allow casting any unmanaged struct to any other unmanaged struct as long as sizeof
says they're of the same size (not gonna dive into the whole sizeof
vs Marshal.SizeOf()
thing here). If you know you're only converting primitive integer types it should be fine though.
Upvotes: 0
Reputation: 19159
There are only 4 types. so simply you can write your own method for that.
private static object CastToUnsigned(object number)
{
Type type = number.GetType();
unchecked
{
if (type == typeof(int)) return (uint)(int)number;
if (type == typeof(long)) return (ulong)(long)number;
if (type == typeof(short)) return (ushort)(short)number;
if (type == typeof(sbyte)) return (byte)(sbyte)number;
}
return null;
}
And here is the test:
short sh = -100;
int i = -100;
long l = -100;
Console.WriteLine(CastToUnsigned(sh));
Console.WriteLine(CastToUnsigned(i));
Console.WriteLine(CastToUnsigned(l));
Outputs
65436
4294967196
18446744073709551516
Update 10/10/2017
with C# 7.1 pattern matching feature for generic types you can now use switch statement.
thanks to @quinmars for his suggestion.
private static object CastToUnsigned<T>(T number) where T : struct
{
unchecked
{
switch (number)
{
case long xlong: return (ulong) xlong;
case int xint: return (uint)xint;
case short xshort: return (ushort) xshort;
case sbyte xsbyte: return (byte) xsbyte;
}
}
return number;
}
Upvotes: 5