[c#] How can I return NULL from a generic method in C#?

I have a generic method with this (dummy) code (yes I'm aware IList has predicates, but my code is not using IList but some other collection, anyway this is irrelevant for the question...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

This gives me a build error

"Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead."

Can I avoid this error?

This question is related to c# generics

The answer is


Your other option would be to to add this to the end of your declaration:

    where T : class
    where T: IList

That way it will allow you to return null.


solution of TheSoftwareJedi works,

also you can archive it with using couple of value and nullable types:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}

Your other option would be to to add this to the end of your declaration:

    where T : class
    where T: IList

That way it will allow you to return null.


For completeness sake, it's good to know you could also do this:

return default;

It returns the same as return default(T);


Your other option would be to to add this to the end of your declaration:

    where T : class
    where T: IList

That way it will allow you to return null.


Add the class constraint as the first constraint to your generic type.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

return default(T);

Below are the two option you can use

return default(T);

or

where T : class, IThing
 return null;

return default(T);

Take the recommendation of the error... and either user default(T) or new T.

You will have to add in a comparison in your code to ensure that it was a valid match if you go that route.

Otherwise, potentially consider an output parameter for "match found".


Add the class constraint as the first constraint to your generic type.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

solution of TheSoftwareJedi works,

also you can archive it with using couple of value and nullable types:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}

Here's a working example for Nullable Enum return values:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}

You can just adjust your constraints:

where T : class

Then returning null is allowed.


return default(T);

Add the class constraint as the first constraint to your generic type.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

You can just adjust your constraints:

where T : class

Then returning null is allowed.


  1. If you have object then need to typecast

    return (T)(object)(employee);
    
  2. if you need to return null.

    return default(T);
    

For me it is works as it is. Where exactly is problem?

public static T FindThing<T>(this IList collection, int id) where T : IThing, new()
{
    foreach (T thing in collection)
    {
        if (thing.Id == id)
            return thing;
        }
    }

    return null; //work
    return (T)null; //work
    return null as T; //work
    return default(T); //work


}

Take the recommendation of the error... and either user default(T) or new T.

You will have to add in a comparison in your code to ensure that it was a valid match if you go that route.

Otherwise, potentially consider an output parameter for "match found".


Your other option would be to to add this to the end of your declaration:

    where T : class
    where T: IList

That way it will allow you to return null.


Below are the two option you can use

return default(T);

or

where T : class, IThing
 return null;

Another alternative to 2 answers presented above. If you change your return type to object, you can return null, while at the same time cast the non-null return.

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

Add the class constraint as the first constraint to your generic type.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()

For me it is works as it is. Where exactly is problem?

public static T FindThing<T>(this IList collection, int id) where T : IThing, new()
{
    foreach (T thing in collection)
    {
        if (thing.Id == id)
            return thing;
        }
    }

    return null; //work
    return (T)null; //work
    return null as T; //work
    return default(T); //work


}

  1. If you have object then need to typecast

    return (T)(object)(employee);
    
  2. if you need to return null.

    return default(T);
    

You can just adjust your constraints:

where T : class

Then returning null is allowed.


Take the recommendation of the error... and either user default(T) or new T.

You will have to add in a comparison in your code to ensure that it was a valid match if you go that route.

Otherwise, potentially consider an output parameter for "match found".


Another alternative to 2 answers presented above. If you change your return type to object, you can return null, while at the same time cast the non-null return.

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}

For completeness sake, it's good to know you could also do this:

return default;

It returns the same as return default(T);


return default(T);

Here's a working example for Nullable Enum return values:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}