user3170354
user3170354

Reputation: 401

Problem with adding items to a generic list

I have the following interface

public interface IInterface
{
    int GetId();
}

ClassA is a generic class but T should implement IInterface

public class ClassA<T> where T : IInterface {

}

ClassB implements IInterface

public class ClassB : IInterface {
    public int GetId() {
        return 1;
    }
}

ClassC is where my problem is, namely adding items to the list.

public class ClassC {
    List<ClassA<IInterface>> list = new List<ClassA<IInterface>>();    

    public void Add<T>(ClassA<T> item) where T : IInterface {
        list.Add(item);
    }
}

The code above gives the following error which makes sense

cannot convert from 'Program.ClassA<T>' to'Program.ClassA<Program.IInterface>'

The core of the problem is in the Add() method where my goal is to be able to add any type of ClassA. I am not sure how to design this in order to achieve the following

ClassC classC = new ClassC();
ClassA<ClassB> classA = new ClassA<ClassB>();
classC.Add(classA);

Any ideas?

Upvotes: 1

Views: 59

Answers (2)

Darkhan Zholmukhanov
Darkhan Zholmukhanov

Reputation: 76

What about using Covariant Generic Type Argument.

public interface IInterface
{
    int GetId();
}

// Contra-variant and covariant generic type argument can be used only in interfaces and delegates
public interface IClassA<out T> where T : IInterface 
{
}

public class ClassA<T> : IClassA<IInterface> where T : IInterface { }

public class ClassB : IInterface
{
    public int GetId()
    {
        return 1;
    }
}

public class ClassC
{
    List<IClassA<IInterface>> list = new List<IClassA<IInterface>>();

    public void Add(IClassA<IInterface> item)
    {
        list.Add(item);
    }
}
public class Test
{
    public static void Run()
    {
        ClassC classC = new ClassC();
        ClassA<ClassB> classA = new ClassA<ClassB>();
        classC.Add(classA);
    }
}

Upvotes: 3

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239814

Depending on the specifics of your design, you may be able to split ClassA in two:

public abstract class ClassA {
  //Stuff that only works in terms of IInterface,
  //maybe with some abstract methods, required constructors, etc
}
public class ClassA<T> : ClassA where T : IInterface {
  //Stuff specific to T
}

You then store ClassAs in your list and cast them to their known concrete type as/when you know what that is and need to work in those terms (e.g. to be able to call ClassA<T> specific functionality)

Upvotes: 0

Related Questions