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