Understanding C # Generators and Nullable Value Type. Returns null or nullable

Suppose I have the following class:

public class GenericClass<T> { public T Find() { //return T if found otherwise null or Nullable<T> } } 

Somewhere I would like to specialize my class using T with class , sometimes with struct . I ran into a problem: I cannot return Nullable<T> if type T not limited to struct .

I would like to provide an implementation of my Find method, which works if T specializes in both class and struct . If Find fails, I would like to return null if T is a class otherwise Nullable<T> .

Is this possible without using reflection? If so, how?

+8
generics null c # nullable mono
source share
3 answers

You can return default(T) .

For the class, this will be null . For any Nullable<T> it will be Nullable<T> without a value (effectively null ).

If you use this with a struct rather than Nullable<T> as a type, default(T) will be the default value for the structure.


If you want to make this work evenly for any class or structure, you will most likely need to return two values ​​- you could use the framework as inspiration here and have a TryXXX method, that is:

 public bool TryFind(out T) 

Then you can use default(T) when the value is not found, and return false. This avoids null types. You can also write this return Tuple<bool, T> or the like if you want to avoid the out parameter, i.e.:

 public Tuple<bool, T> Find() 

The last option, potentially, was to make your class not shared, and then use a couple of common methods:

 class YourClass // Non generic { public T FindReference<T>() where T : class { // ... return null; } public Nullable<T> FindValue<T>() where T : struct { // ... return default(T); } } 

Note that you need different names, since you cannot overload a method based only on the return type.

+15
source share

I would use the following solution:

 public Boolean Find(out T result) { // Pseudo code if (FindItem == true) { result = ItemFound; return true; } result = default(T); return false; } 

Why? Since Nullable<T> only accepts a structure, and the method above supports both classes and structures.

+2
source share

As Reed said, you can return default(T) .

In my opinion, this has one big drawback: if your method claims that default(T) returned if the item was not found, you lose the ability to return default values ​​for value types (for example, returning 0 for Find<int> can usually be a valid return value).

I would rather go for something like this

 public class GenericClass<T> { public Option<T> Find() { //return Option.Some(item) if found otherwise Option.None<T>() } } public static class Option { public static Option<T> None<T>() { return new Option<T>(default(T), false); } public static Option<T> Some<T>(T value) { return new Option<T>(value, true); } } public sealed class Option<T> { private readonly T m_Value; private readonly bool m_HasValue; public void Option(T value, bool hasValue) { m_Value = value; m_HasValue = hasValue; } public bool HasValue { get { return m_HasValue; } } public T Value { get { return m_Value; } } } 
0
source share

All Articles