The following pair of functions attempt to replicate the null conditional operator available in C# 6.0:
public static TResult Bind<T, TResult>(this T obj, Func<T, TResult> func)
where T : class
{
return obj == null ? default(TResult) : func(obj);
}
public static TResult Bind<T, TResult>(this Nullable<T> obj, Func<T, TResult> func)
where T : struct
{
return obj.HasValue ? func(obj.Value) : default(TResult);
}
The first function is constrained to classes and for a String s allows me to write something like:
var x = s.Bind(a => a.Substring(1));
The second function is where I am running into trouble. For example, given a int? number I would like to write:
var y = number.Bind(a => a + 1);
However, this gives me the following error:
The call is ambiguous between the following methods or properties: 'BindingExtensions.Bind<T, TResult>(T, Func<T, TResult>)' and 'BindingExtensions.Bind<T, TResult>(T?, Func<T, TResult>)'
I'm guessing that this has something to do with the interplay between the type inference of the anonymous function and the method overload resolution. If I specify the type of a as int than it compiles just fine.
var y = number.Bind((int a) => a + 1);
However, this is clearly less than desirable. Can anyone tell me why the compiler thinks the above call to bind is ambiguous and/or offer a way to fix this? I know I could simply name the two functions differently, but what fun is that?
Overloaded functions cannot be disambiguated by type constraints (see "Generic constraints, where T : struct and where T : class"). Any nullable type N satisfies N : T and N : Nullable<T>, required by the former and latter Bind definitions respectively. I am guessing that number is of type Nullable<int> or similar.
var x = s.Bind(a => a.Substring(1));
This is unambiguous because s is of type string and for all T not string : Nullable<T>, so only the first overload is acceptable.
var y = number.Bind(a => a + 1);
This is ambiguous because the type of a => a + 1 may be inferred as either Func<int?,int?> or Func<int,int>. If inferred as Func<int?,int?> the first overload applies, and if inferred as Func<int,int> the second overload applies.
var y = number.Bind((int a) => a + 1);
This is unambiguous if number is of type Nullable<int>, for example. For the first overload for all T not T : Nullable<int> and T : int, so it does not apply. For the second overload you just need T : int which is easily satisfied by T = int.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With