Bryan Bryan - 29 days ago 10
C# Question

Specify Generic type and interface

I need to have a list where all items extend class A and implement interface I. Additionally class A might be multiple parents up in the hierarchy.

If all the classes were direct descendants of class A I could just use an Abstract class that implements I as the generic and use that, but my use case doesn't allow for this.

is there a way to tell a List that its elements must both extend class A and implement interface I ?

List<A,I>
? If not is there another way around this?

Example Code:

public class A
{
// Class belongs to a third party library
}

public class B : A
{
// Class belongs to a third party library
public string Text{ get; set; }
}

public class C : A
{
// Class belongs to a third party library
public string Other{ get; set; }
}

interface I
{
// Belongs to me
bool shouldSend();
string getName();
string getValue();
}

public class MyClass : B, I
{
public string Name{ get; set; }

public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}

public string getValue()
{
return Text;
}

public bool shouldSend()
{
return true;
}
}

public class MyClass2 : C, I
{
public string Name{ get; set; }

public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}

public string getValue()
{
return Other;
}

public bool shouldSend()
{
return true;
}
}

public class mainActions
{
// Here is where I need the list to use both restrictions
public List<A,I> myList;
// The class I need to use these things in
public function mainActions(List<ObjectWithName> elements)
{
ThirdPartyCollection TPC = new ThirdPartyCollection();
foreach(var el in elements)
{
MyList.Add(new MyClass(el));
MyList.Add(new MyClass2(el));
// TPC.Add accepts implementations of A here
TPC.Add(MyList.ElementAt(MyList.Count - 1));
TPC.Add(MyList.ElementAt(MyList.Count - 2));
}


}

public function doThisLater()
{
foreach(var el in myList)
{
if(el.shouldSend())
{
// I need an implementation of I here
doSomethingElse(el.getName(), el.getValue());
}
}
}
}


EDIT: For anyone coming in search of an answer here in the future, it doesn't seem to be possible. Instead I used @servys answer and made a new list to hold my sub class objects:

public class MyList<T> : List<T> where T : A, I
{
}


Then I kept different lists for each subclass:

protected MyList<MyClass> MCList = new MyList<MyClass>();
protected MyList<MyClass2> MCList2 = new MyList<MyClass2>();

Answer Source

When you specify generic constraints you can specify as many as you want, and all of them must be met, so you can simply add a generic constraint of A and I to your type, and a type has to meet both of those constraints to be a valid generic argument.

public class ClassThatNeedsABetterName<T> : List<T>
    where T : A, I
{ }