I want to be able to declare a generic instance that takes a base class as a type parameter and then later assign it to a generic that takes the subclass as the parameter. I have been able to do similar things in Java, but I'm stuck here in C#.
The best use case for a problem like this would be to map different interactions to two class types, which I have done in this code snippet. I tried to declare a Base class and classes A and B that derive from it. Then I want to map a function which takes the two classes as parameters.
class Program
{
public class Base {}
public class A : Base {}
public class B : Base {}
public class TypePair
{
private Type left;
private Type right;
public TypePair(Type left, Type right)
{
this.left = left;
this.right = right;
}
}
public static Dictionary<TypePair, Func<Base, Base, bool>> typeMap = new Dictionary<TypePair, Func<Base, Base, bool>>();
public static bool doStuffWithAandB(A a, B b)
{
Console.WriteLine("Did stuff with a and b!");
return true;
}
public static void Main(string[] args)
{
var typePair = new TypePair(typeof(A), typeof(B));
typeMap.Add(typePair, doStuffWithAandB); // <- Compiler error :(
typeMap[typePair](new A(), new B());
}
}
The compiler expects a generic (Func) like doStuffWithAandB(Base a, Base b) and not doStuffWithAandB(A a, B b). If C# does not allow such a functionality. Why is that and are the better solutions to problems like these?
Only interfaces and delegates can be specified as variant in C#. So if you define an IGeneric<T>
interface, you can assing it to a Generic<SubClass>
:
interface IGeneric<out T> { }
class Generic<T> : IGeneric<T> { }
class Base { }
class SubClass : Base { }
IGeneric<Base> obj = new Generic<SubClass>();
In C# 8.0+, interfaces may contain default implementations: https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/
You can't assing a Func<Base, Base, bool>
to a Func<Derived, SubClass , bool>
because the in parameter types T1
and T2
are contravariant:
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)
Please refer to @Eric Lippert's answer here for more information about this.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다