Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics, Nullable, Type inference and function signature conflict

I've this code :

public async static Task<T?> RequestValue1<T>(Command requestCommand)
                    where T : struct 
{
    // Whatever
}

public async static Task<T> RequestValue2<T>(Command requestCommand)
                    where T : class 
{
    // Whatever
}

I want to have the same name for my two methods. Is this even possible ?

My problems:

  • I have to write two different methods because of the return type (I want it to be null if the request failed or a value if the request succeed) which is Nullable<T> if T is a value type, and an instance of T if T is a reference type.
  • async doesn't allow ref/out, so without a method argument of type T, T isn't inferred and my two methods cannot have the same name (signature conflict, as generic constraints doesn't works for signature conflict resolution if T isn't inferred)

Currently this code works but I don't like this strange function calls between "RequestValue1" and "RequestValue2".

like image 205
Nicolas Voron Avatar asked Oct 06 '22 14:10

Nicolas Voron


1 Answers

You could create your own Option type and use that to indicate if a value is returned or not:

public async static Task<Option<T>> RequestValue<T>(Command requestCommand) {
  ...
}

Update: the intent of the Option<T> type is to replace nulls and Nullable<T>s, but if you'd still like to use them, you can use these extension methods to bridge the gap:

public static class OptionExtensions {
  public static T? GetNullableValue<T>(this Option<T> option) where T : struct {
    return option.HasValue ? (T?)option.Value : null;
  }
  public static T GetValueOrNull<T>(this Option<T> option) where T : class {
    return option.HasValue ? option.Value : null;
  }
}
like image 105
Jordão Avatar answered Oct 10 '22 01:10

Jordão