I'm encountering a compilation error in C# .NET 8.0 when trying to pass a Dictionary with a tuple as its key to a method. The tuple consists of a base class and another class, but when I try to use a derived class in place of the base class within the tuple, the code fails to compile. Here's a simplified version of my code:
class A{};
class B : A {};
class X{};
void bar(Dictionary<(A sup, X oth), X> MyDicArg) {
// Do something with Dictionary using that tuple
}
void foo() {
var arg = new Dictionary<(B sup, X oth), X>();
bar(arg); // Compilation error here
}
Since B is a subclass of A, I thought I could use a Dictionary with a key of (B, X) where a Dictionary with a key of (A, X) is expected due to implicit upcasting, but it does not seem to happening.
Could someone explain why this type mismatch occurs and how I might work around this issue? Is there a way to make the method accept a dictionary with a derived class in the tuple key, or do I need to adjust my approach?
The term you are looking for is covariance (And its relative, contravariance.) Unfortunately, tuples in C# are neither covariant nor contravariant, because they are
structs, notinterfaces, and in C# only interfaces support covariance/contravariance.In your specific example you should consider the limitation as just fine, because if this limitation was not there, you would be allowed to potentially shoot yourself in the foot.
This is because
foo()has a dictionary of a more-derived class, and you wanted it to hand-out this dictionary tobar()which would treat it as containing a less-derived class, but you are usingDictionary, notIReadOnlyDictionary, sobar()is free to add a less-derived class into the dictionary, thus wreaking havoc intofoo().