Open xposure opened 3 years ago
This doesn't work in C# - if it WERE allowed then it would only work on methods that had no overloads at all. I agree with their design decision to not allow it.
public static void Bind<T>(Action<T> dlg)
{
}
public static void MethodA(int a)
{
}
public static void Main(String[] args)
{
// This works
Bind<int>(MethodA);
// This does not work
Bind(MethodA);
}
Any chance you have a link or more information for C# ? I wouldn't mind reading over it.
I guess it must be in here somewhere https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-334.pdf
Seems like its related to this https://stackoverflow.com/questions/3630153/generic-extension-method-type-argument-cannot-be-inferred-from-the-usage/3630202#3630202
There appears to be debate if this should be the correct behavior.
As for method overloading, from that I could understand, C# just matches the more specialized version. If you have a scenario where they are equally specialized it just throws an ambigious error.
What I meant was this:
public static void Bind<T>(Action<T> dlg)
{
}
public static void MethodA(int a)
{
}
public static void MethodA(float a)
{
}
public static void Main(String[] args)
{
// This works
Bind<int>(MethodA);
// This does not work
Bind(MethodA);
}
There is absolutely no way to infer which MethodA was the desired one.
You may think that this should be handled as a normal "ambiguous method" just like at an invocation callsite, but in those cases you CAN add a new method overload without causing errors, whereas this requested feature would 100% fail every time an overload was added.
If you would figure out how to handle my discriminated union types, this wouldn't be an issue ;)
This isn't a one to one comparison, here is something that fails to match but works in C#. In the spec it says it will infer a return type if all the other types are known.
//public delegate Result Func<T, Result>(T t);
public static class Test
{
public struct XYZ
{
public int x;
public int y;
}
public static K Min<T, K, F>(this List<T> items, Func<T, K> dlg)
//where bool : operator K < K
{
var enumerator = items.GetEnumerator();
if (!enumerator.MoveNext())
return default;
var t = dlg(enumerator.Current);
while (enumerator.MoveNext())
{
var r = dlg(enumerator.Current);
//if (r < t) removed due to lack of operator constraints
t = r;
}
return t;
}
public static void TestMe()
{
var test = new List<XYZ>();
var t = test.Min(it => it.x);
// let t = test.Min((it) => it.x)); // Can't determine K
}
}
90d3d3a
I think the compiler should be able to determine the implicit generic type here. The param in the method signature is T.