tags:

views:

147

answers:

7

I have an Oracle data table fetching columns that be null. So I figure to keep the code nice and simple that I'd use the ?? operand. AlternatePhoneNumber is a string in my C# model.

AlternatePhoneNumber = customer.AlternatePhoneNumber ?? ""

However, even with that code I still get the error.

System.InvalidCastException: Unable to cast object of type 'System.DBNull' to type 'System.String'.

I know what the error means but why is ?? not usable on DBNull? Isn't null and DBNull essentially the same?

Thank you.

+15  A: 

The ?? operator only applies to actual nulls.

null and DBNull.Value are not the same; DBNull.Value is simply a placeholder object.

Also, that exception is coming from inside the AlternatePhoneNumber property, before your ?? operator executes. (Your code doesn't have a cast).

If customer is a row in a typed dataset, change the column's NullValue property in the designer.

SLaks
Woah, great answer. Thanks for the in depth answer.
Mike
+3  A: 

null and DBNull are not the same. System.DBNull is an actual object.

Moose
+2  A: 

The problem is that AlternatePhoneNumber is a string. DBNull is not.

Try this instead:

AlternatePhoneNumber = (customer.AlternatePhoneNumber as string) ?? ""
Toby
The `AlternatePhoneNumber` property is already a string. This won't help.
SLaks
If it's a string, then it can't be a DBNull.
Toby
+2  A: 

DBNull is a type with a single value, and is not the same as a null string reference, which is why you can't use ??. You could do this however:

string alternativePhoneNumber = DBNull.Value.Equals(customer) ? string.Empty : ((Customer)customer).AlternatePhoneNumber;
Lee
This code is wrong on many levels. `DBNull` is miscapitalized. You shouldn't bother calling `.Equals`. `Customer` is neither`DBNull` nor a `string`.
SLaks
+2  A: 

Do this:

public T IfNull<T>(object o, T value)
{
   return (o == DbNull.Value) ? value : (T)o;       
}
Andrey
+1 for this answer. Very helpful!
Turing Complete
+1  A: 

As other replies state, null means a reference that refers to no object, while DBNull is a class supplied by ADO.NET to indicate when a field or value is NULL at the database (or in a DataTable).

While you can use the conditional (ternary) operator (?:) to do what you want:

AlternatePhoneNumber = customer.AlternatePhoneNumber is DBNull 
                           ? "" 
                           : customer.AlternatePhoneNumber;

I tend to wrap this up in an extension method:

static class NullExtensions
{
    public static T WhenNull<T>( this object value, T whenNullValue )
    {
        return (value == null || value is DBNull)
            ? whenNullValue
            : (T)value;
    }
}

which I find makes the code easier to read and understand.

AlternatePhoneNumber = customer.AlternatePhoneNumber.WhenNull( "" );
LBushkin
This won't compile. `AlternatePhoneNumber` is a string.
SLaks
@SLaks: Which part won't compile? The extension method accepts an `object` and returns a type that matches the default value.
LBushkin
`customer.AlternatePhoneNumber is DBNull` won't compile because it's statically typed as `string`. Your extension method won't help, because the exception is coming from inside the property.
SLaks
@SLaks: Ah, I see what you're saying. Ye, the OP needs to change the implementation of the property in that case.
LBushkin
+1  A: 

DBNull is NOT a real "null".

The "??" - operator detects only null - references, not objects that emulate "null" behavior.

Turing Complete