I've searched and read/studied as much as seemed reasonable prior to posting this. I have found similar questions, but most posts actually relate more to passing "List of a derived types" to functions calls that require "List of a base type". I can appreciate the animal examples and feel like I have a much better grasp after my studies.
That being said, I still can't figure out how to solve in my particular use-case. I have a need to aggregate instances of a "GenericClass of TestInterface(s)" in a collection. I have copied/pasted below my best effort at what might seem like the best way to accomplish the tasks.
namespace Covariance
{
class Program
{
protected static ISet<GenericClass<TestInterface>> set = new HashSet<GenericClass<TestInterface>>();
static void Main(string[] args)
{
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}
class GenericClass<TemplateClass> where TemplateClass : TestInterface
{
TemplateClass goo;
}
public interface TestInterface
{
void test();
}
public class A : TestInterface
{
public void test()
{
}
}
class B : A
{
}
}
The above code fails with the following compile errors:
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
error CS1503: Argument 1: cannot convert from 'Covariance.GenericClass' to 'Covariance.GenericClass'
Any help/guidance or relevant links would be much appreciated. Once again, my apologies if this is a duplicate question. Thank You!
You can only declare variance modifiers (in, out) on generic interfaces, not types. So one way to solve this problem would be to declare interface for your GenericClass
, like this:
interface IGenericClass<out TemplateClass> where TemplateClass : TestInterface {
TemplateClass goo { get; }
}
class GenericClass<TemplateClass> : IGenericClass<TemplateClass> where TemplateClass : TestInterface
{
public TemplateClass goo { get; }
}
And then
class Program {
protected static ISet<IGenericClass<TestInterface>> set = new HashSet<IGenericClass<TestInterface>>();
static void Main(string[] args) {
set.Add(new GenericClass<A>());
set.Add(new GenericClass<B>());
}
}