I have something that looks like the following scenario:
interface IExample<T>
{
public IExample<T> First();
public IExample<T2> Second<T2>();
}
class Foo<T> : IExample<T>
{
public Foo() {}
public IExample<T> First() => new Foo<T>() {};
public IExample<T2> Second<T2>() => new Foo<T2>() {};
public Foo<T> Third() => new Foo<T>() {};
}
public static class Main {
public static void Run() {
var bar = (new Foo<string>()).First().Third();
}
}
This does not work, because First() returns an IExample<T>, which does not have Third().
So in order to make it return itself, I have tried these two things:
interface IExample<T, out ExampleDerivedType>
{
public ExampleDerivedType First();
// Doesn't work because it expects Foo<T> instead of Foo<T2>
public ExampleDerivedType Second<T2>();
}
class Foo<T> : IExample<T, Foo<T>>
interface IExample<T, out ExampleDerivedType>
// // Infinite recursion?
// where ExampleDerivedType : IExample<T, ExampleDerivedType>
// // Does this kind of constraint even exist?
// where ExampleDerivedType is generic with one argument
{
public ExampleDerivedType<T> First();
public ExampleDerivedType<T2> Second<T2>();
}
class Foo<T> : IExample<T, Foo>
I know I can explicitly redefine the methods in this manner:
class Foo<T> : IExample<T>
{
public Foo() {}
IExample<T> IExample<T>.First() => First();
public Foo<T> First() => new Foo<T>() {};
IExample<T2> IExample<T>.Second<T2>() => Second<T2>();
public Foo<T2> Second<T2>() => new Foo<T2>() {};
public Foo<T> Third() => new Foo<T>() {};
}
But the solution I'm aiming for above is more appealing. I'm wondering whether it is
- Possible
- Possible in theory, but C# can not do it without help from either reflection or roslyn generators.
- Impossible, because it is logically flawed and the compiler lacks the information it needs.
Right now, I'm guessing it's the middle one, but I'd be happy to be proven wrong.