5

Is it possible to make the following code compile in C#? I do compile similar in Java.

public interface IInterface
{
    ...
}

public class Class1 : IInterface
{
    ...
}

public abstract class Base<T> where T : IInterface
{
    ...
}

public class Class2<T> : Base<T> where T : IInterface
{
    ...
}

.
.
.

public SomeMethod()
{
    List<Base<IInterface>> list = new List<Base<IInterface>>();
    Class2<Class1> item = new Class2<Class1>();
    list.Add(item); // Compile error here
}
Floris Velleman
  • 4,848
  • 4
  • 29
  • 46
Bumbala
  • 315
  • 3
  • 9
  • possible duplicate of [Covariance in C# generic class](http://stackoverflow.com/questions/16317541/covariance-in-c-sharp-generic-class) – nawfal Jul 10 '14 at 06:17

3 Answers3

7

No, that is not legal in C#. C# 4 and above support covariance and contravariance of generic interfaces and generic delegates when they are constructed with reference types. So for example, IEnumerable<T> is covariant, so you could say:

List<Giraffe> giraffes = new List<Giraffe>() { ... };
IEnumerable<Animal> animals = giraffes;

but not

List<Animal> animals = giraffes;

Because a list of animals can have a tiger inserted into it, but a list of giraffes cannot.

Do a web search on covariance and contravariance in C# and you'll find lots of articles on it.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • From what I read in the following link: http://msdn.microsoft.com/en-us/library/dd799517.aspx Only interfaces and delegates can be covariant. So it looks like I have to find another solution. Thanks anyway. – Bumbala Sep 29 '13 at 15:51
3

Looks like .NET Framework 4.0 supports covariance in generic interfaces and delegates. So, I happened to compile the code by adding a generic interface.

public interface IInterface
{
    ...
}

public class Class1 : IInterface
{
    ...
}

public interface IBase<out T> where T: IInterface
{
    // Need to add out keyword for covariance.
}

public class Base<T> : IBase<T> where T : IInterface
{
    ...
}

public class Class2<T> : Base<T> where T : IInterface
{
    ...
}

.
.
.

public SomeMethod()
{
    List<IBase<IInterface>> list = new List<IBase<IInterface>>();
    Class2<Class1> item = new Class2<Class1>();
    list.Add(item); // No compile time error here.
}
Bumbala
  • 315
  • 3
  • 9
0

you cannot use generic like this.list type is IInterface but you try to add Class1 type into the list.it should be as follows..

        List<Base<Class1>> list = new List<Base<Class1>>();
        Class2<Class1> item = new Class2<Class1>();
        list.Add(item); 
Thilina H
  • 5,754
  • 6
  • 26
  • 56
  • The list is just an example. Consider this: public void SomeMethod() { AnotherMethod(new Class2()); } public void AnotherMethod(Base obj) { ... } – Bumbala Sep 29 '13 at 11:12