Reputation: 679
I have a
public class A<T> where T : IBase
{
//Does something
}
I need a second class that behaves like a collection of class A
public class B<A<T>> : IEnumerable<A<T>> where T : IBase
{
}
The problem is that I do not want to create classes like
public class B<A<MyCustomObjectP>> : IEnumerable<A<MyCustomObjectP>>
{
}
public class C<A<MyCustomObjectQ>> : IEnumerable<A<MyCustomObjectQ>>
{
}
and so on.. I would like to let the CustomObject be a generic type parameter that implements IBase.
I found that even doing this is illegal:
public class B<T, U> : IEnumerable<T> where T : A<U> where U : IBase
{
}
How could I achieve this type of behaviour, if this is illegal? Is there a better design pattern of sorts that might help?
Upvotes: 1
Views: 93
Reputation: 26999
You wrote that you need a second class that behaves like a collection of class A
.
Since you have other classes (like B
) inheriting from IBase
as well, which you want to add, you can make the collection a collection of IBase
.
Hence the solution would look like this (note that I have used List
but you can easily replace that by IEnumerable
- but then you have to implement methods like .Add
yourself):
void Main()
{
var items = new CollectionOf<IBase>(); // create list of IBase elements
items.Add(new A() { myProperty = "Hello" }); // create object of A and add it to list
items.Add(new B() { myProperty = "World" }); // create object of B and add it to list
foreach(var item in items)
{
Console.WriteLine(item.myProperty);
}
}
// this is the collection class you asked for
public class CollectionOf<U>: List<U>
where U: IBase
{
// collection class enumerating A
// note you could have used IEnumerable instead of List
}
public class A: IBase
{
// class A that implements IBase
public string myProperty { get; set; }
}
public class B: IBase
{
// class B that implements IBase too
public string myProperty { get; set; }
}
public interface IBase {
// some inteface
string myProperty { get; set; }
}
Upvotes: 0
Reputation: 10947
The IBase
constraint is defined on A<T>
, so it must be defined again on all generic classes, that want to use A<U>
(using U
to distinguish from T
in A<T>
class definition, but it can be called anything). You should be able to do simply:
public class B<T> : IEnumerable<A<T>> where T : IBase { ... }
Upvotes: 1