1

A similar question, but without casting the T parameter.

This does not work

public T GetValueG<T>(string Query)
{
    object value = DBNull.Value;    // Read from Database which can return DBNull
    if (value is DBNull)
        return (T)null;
    else
        return (T)value;
}

Error CS0037 Cannot convert null to 'T' because it is a non-nullable value type


But this works

public T GetValueG<T>(string Query)
{
    object value = DBNull.Value;    // Read from Database which can return DBNull
    if (value is DBNull)
        value = null;

    return (T)value;
}

I know that using constraint type where T: struct will make T to be able to be cast with null directly.

But in the second approach, why does it accept an object which is 100% can be null? Why can't I return null directly without an object or something either?

deveton
  • 291
  • 4
  • 26
  • 3
    Why would you do `(T)null` in the first place? return `default(T)` or just null. – Adrian Nov 29 '19 at 23:18
  • 2
    default(T) for integers and decimals returns zero. I don't need that.. also geenric-type can't return null if it's not nullable generic type. and i want accept null for any Database reader. not default of value. – deveton Nov 29 '19 at 23:19
  • I agree, returning `default(T)` is probably best in this case, without knowing more details as to why it needs to specifically be `null`. – Matt U Nov 29 '19 at 23:19
  • 2
    Matt U and Adriani6, Guys i don't want default of type. i always return null for DBNulls. thats all ! :) – deveton Nov 29 '19 at 23:21
  • 2
    @deveton But you can't assign null to an integer.. unless it's a nullable integer.. `GetValueG()` then do `default(T)` as your return. In fact, putting the generic type as `int?` `bool?` etc will be sufficient to just return `null` without casting - but that will obviously leave a possible exception. – Adrian Nov 29 '19 at 23:24
  • Will this work: `return (T)((object)null);` – CodingYoshi Nov 29 '19 at 23:43
  • @CodingYoshi No, it will not. Again, integers are not nullable. That will throw a NullRef Exception. – Adrian Nov 29 '19 at 23:44
  • @adriani6 Almost correct. For `T?` it wil work. – CodingYoshi Nov 29 '19 at 23:53
  • @CodingYoshi Well, yes... same result as `default(T)` with `T?` though, not sure why a dual cast is beneficial either way. – Adrian Nov 29 '19 at 23:59
  • Re *"something either"*: Do you mean *"something else"*? – Peter Mortensen Dec 01 '19 at 05:25

1 Answers1

3

What you're trying to do is wrong. Integers are non-nullable types, meaning you can't return null as a value of int or any other not nullable type (as the name suggests...)

Take for example:

int myInt = null; - your IDE will right away flag it up with integer being a non-nullable type.

What you want to do is use a nullable type of the actual type you're trying to use e.g. int? or bool?.

You should be returning null or default(T) rather than (T)null that doesn't make sense, as you can't cast null to e.g. a class type, it'll throw Object Reference Not Set To An Instance....

I would change your function to the following:

public T GetValueG<T>(string Query)
{

    object value = DBNull.Value;    // Read from Database which can return DBNull
    if (value is DBNull)
        return default(T);  // `return default;` also valid since C# 7.1 

    return (T)value;
}

If a value can be null in your database, then your model should be implementing a nullable of that type to avoid casting exceptions later down the line.

Your function should be called as such GetValueG<int?>("<query>");.

Default values for non-nullables can be found here.

In your code, rather than checking for null values using myInt == null you'd do myNullableInt.HasValue.

Summary

The default keyword. will return null for nullable types by default. and default values for other non-nullable types. as OP needs.

default(bool?) -> null

default(bool) -> false

Theraot
  • 31,890
  • 5
  • 57
  • 86
Adrian
  • 8,271
  • 2
  • 26
  • 43
  • oh, I never thought default(bool?) will return null. so yes your approach is a good one. using default is a must with nullable and non-nullable types. I will modify something to make it more concise. – deveton Nov 30 '19 at 01:44