It's helpful to understand why this is illegal. The feature you want is formal parameter type covariance, and very few languages offer it. (Eiffel, I think has this as a feature.) It is not often found in languages because it is not safe! Let me illustrate with an example:
class Animal {}
class Lion : Animal { public void Roar() { } }
class Giraffe : Animal { }
interface IFoo { void M(Animal a); }
class C : IFoo
{
public void M(Lion lion) { lion.Roar(); }
}
class P
{
public static void Main()
{
IFoo foo = new C();
foo.M(new Giraffe());
}
}
And we just made a giraffe roar.
If you look at all those type conversions, the only one that can sensibly be made illegal is matching C.M(Giraffe)
to IFoo.M(Animal)
.
Now, formal parameter type contravariance is typesafe but it is not legal in C# except in some very limited circumstances. If C# supported it, which it does not, then you could safely do something like this:
interface IBar { void M(Giraffe g); }
class D : IBar
{
public void M(Animal animal) { ... }
}
class P
{
public static void Main()
{
IBar bar = new D();
bar.M(new Giraffe());
}
}
See what happened there? IFoo.M says "I can take a giraffe", and C.M says "I can accept any giraffe because in fact I can accept any animal". That would be typesafe if C# supported it, but it only supports it in two ways:
- Contravariant generic delegate and interface conversions.
- Contravariant method group conversions to delegate types.
An example of the first is that an expression of type IComparable<Animal>
may be assigned to a variable of type IComparable<Giraffe>
by the same logic: a method that compares two animals can be used where a method that compares two giraffes is needed. This was added in C# 4.
An example of the second is:
delegate void MyFunction(Giraffe g);
...
D d = new D();
MyFunction myfunc = d.M;
Again, we need a function that takes a Giraffe, and we supply one that takes any Animal. This feature was added in C# 2.