Alexander Hryk
Alexander Hryk

Reputation: 585

Cast negative number to unsigned types (ushort, uint or ulong)

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

Answers (2)

Frederik Hoeft
Frederik Hoeft

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

M.kazem Akhgary
M.kazem Akhgary

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

Related Questions