s.m.
s.m.

Reputation: 8043

Casting boxed byte

I'm trying to write an extension method that, given a value, will return

Yeah, that's not the clearest explanation, maybe some code will make what I'm trying to accomplish obvious.

public static T GetValueOrDefault<T>(this object value) {
    if (value == DBNull.Value)
        return default(T);
    else
        return (T)value;
}

As long as value's boxed type is the same as T, this method works correctly.

The real fun kicks in when the types are different, for instance the boxed value is byte and T is int.

Is there an elegant way to make this work?

Doing some typechecking manually to first cast from e.g. object to byte and then from byte to T, of course, won't work.

Edit

The proposed solution should work with enums too, not only with "standard" types.

Upvotes: 6

Views: 145

Answers (3)

Hans Passant
Hans Passant

Reputation: 941635

    public static T GetValueOrDefault<T>(this object value) {
        if (value == DBNull.Value) {
            return default(T);
        }
        else {
            if (typeof(T).IsEnum) value = Enum.ToObject(typeof(T), Convert.ToInt64(value));
            return (T)Convert.ChangeType(value, typeof(T));
        }
    }

Upvotes: 2

Christian Hayter
Christian Hayter

Reputation: 31071

Call your method with a type argument that exactly matches the database value, then cast it to what you actually want, e.g.

int result = (int) row["NullableByteColumn"].GetValueOrDefault<byte>();

I think this is reasonable because the code clearly separates the two different concepts that are at work here:

  • Reading a database value into the correct equivalent .NET data type.
  • Mapping the database access layer type into the required business logic layer type.

This separation of responsibility becomes more important if the required data type is something further removed from int and requires more complex translation, e.g. an enum, a string, or a day offset from a date.

Upvotes: 4

CodeCaster
CodeCaster

Reputation: 151604

This works for me:

class Program
{
    static void Main(string[] args)
    {
        Byte myByte = 5;

        object myObject = (object)myByte;

        int myInt = myObject.GetValueOrDefault<Byte>();
        Console.WriteLine(myInt); // 5

        myObject = DBNull.Value;

        myInt = myObject.GetValueOrDefault<Byte>();
        Console.WriteLine(myInt); // 0

        Console.ReadKey(true);
    }
}

public static class ObjectExtension
{
    public static T GetValueOrDefault<T>(this object value)
    {
        if (value == DBNull.Value)
        {
            return default(T);
        }
        else
        {
            return (T)value;
        }
    }
}

Upvotes: 0

Related Questions