C
C#2mo ago
PixxelKick

✅ Generic Binding Func<...> when you have inner generics is giving me "cannot infer types"

Been banging my head against this one for awhile now, I just cant seem to get the type inference to work right. So as an example I have this code that demonstrates the issue:
public record TestParent<TChild>(TChild Child);

private static TestParent<int> ReturnsParent(
Unit unit
) => new(0);

private static Unit ConsumesParent(
TestParent<int> parent
) => Unit.Default;

public static void TestInferReturn<TChild>(Func<Unit, TestParent<TChild>> parent) {}

public static void TestInferArg<TChild>(Func<TestParent<TChild>, Unit> parent) {}

public static void TestStuff()
{
TestInferReturn(ReturnsParent);

TestInferArg(ConsumesParent);
}
public record TestParent<TChild>(TChild Child);

private static TestParent<int> ReturnsParent(
Unit unit
) => new(0);

private static Unit ConsumesParent(
TestParent<int> parent
) => Unit.Default;

public static void TestInferReturn<TChild>(Func<Unit, TestParent<TChild>> parent) {}

public static void TestInferArg<TChild>(Func<TestParent<TChild>, Unit> parent) {}

public static void TestStuff()
{
TestInferReturn(ReturnsParent);

TestInferArg(ConsumesParent);
}
The issue occurs on this line:
TestInferArg(ConsumesParent);
TestInferArg(ConsumesParent);
This one gives me the usual error:
The type arguments for method 'Routing.TestInferArg<TChild>(Func<Routing.TestParent<TChild>, Unit>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. [CS0411]
Note: this line does not give any error
TestInferReturn(ReturnsParent);
TestInferReturn(ReturnsParent);
I assume this happens because Func is declared as such?
public delegate TResult Func<in T, out TResult>(T arg)
public delegate TResult Func<in T, out TResult>(T arg)
Namely, that in T messes with the type inference of a nested type, whereas out TResult is why it can succeed in infering it? Anyone know an approach to deal with this?
1 Reply
PixxelKick
PixxelKickOP2mo ago
Hmm, even tried doing this:
public delegate TResult MyFunc<T, TResult>(T arg);
public delegate TResult MyFunc<T, TResult>(T arg);
And then modified TestInferArg as such
public static void TestInferArg<TChild>(MyFunc<TestParent<TChild>, Unit> parent) {}
public static void TestInferArg<TChild>(MyFunc<TestParent<TChild>, Unit> parent) {}
And it still just cant seem to handle infering the type when its specifically an arg. It handles the return type of the function just fine, bleh Lol even this cant infer the type? wat?
public record TestInput<TChild>(TChild Child);

public record TestOutput : IBoundTo<int>;

public interface IBoundTo<TChild>;

public static IBoundTo<int> TestBound(
TestInput<int> input
) => new TestOutput();

public static void TestInferBound<TChild>(
Func<TestInput<TChild>, IBoundTo<TChild>> method
) {}

public static void TestStuff()
{
TestInferBound(TestBound);
}
public record TestInput<TChild>(TChild Child);

public record TestOutput : IBoundTo<int>;

public interface IBoundTo<TChild>;

public static IBoundTo<int> TestBound(
TestInput<int> input
) => new TestOutput();

public static void TestInferBound<TChild>(
Func<TestInput<TChild>, IBoundTo<TChild>> method
) {}

public static void TestStuff()
{
TestInferBound(TestBound);
}
I woulda that that for sure would work, since the return type specifies TChild is an int now, I dunno why the compiler cant at least figure this one out now Declaring it this way also doesnt work
public static void TestInferBound<TChild, TResult>(
Func<TestInput<TChild>, TResult> method
)
where TResult : IBoundTo<TChild>
{}
public static void TestInferBound<TChild, TResult>(
Func<TestInput<TChild>, TResult> method
)
where TResult : IBoundTo<TChild>
{}
Even this most minimalist example shows how it just cannot seem to infer it, blegh
public record TestInput<TChild>(TChild Child);

public static int TestBound(
TestInput<int> input
) => 1

public static void TestInferBound<TChild>(
Func<TestInput<TChild>, TChild> method
) {}

public static void TestStuff()
{
TestInferBound(TestBound);
}
public record TestInput<TChild>(TChild Child);

public static int TestBound(
TestInput<int> input
) => 1

public static void TestInferBound<TChild>(
Func<TestInput<TChild>, TChild> method
) {}

public static void TestStuff()
{
TestInferBound(TestBound);
}
That's cuz an anonymous function is already a Func<...> so the types match now Whereas a method has to be converted to a Func which I guess makes the compiler fail to figure it out?

Did you find this page helpful?