Я прочитал все о Covariance, Contravariance и Invariance, но я все еще не понимаю, как разработать свой код

Я искал и читал / изучал столько, сколько казалось разумным до публикации этого. Я нашел похожие вопросы, но большинство постов на самом деле больше связаны с передачей "Списка производных типов" вызовам функций, которые требуют "Список базового типа". Я могу оценить примеры животных и чувствую, что у меня есть намного лучшее понимание после моих исследований.

При этом, я все еще не могу понять, как решить в моем конкретном случае использования. У меня есть необходимость агрегировать экземпляры "GenericClass of TestInterface(s)" в коллекции. Я скопировал / вставил ниже всех моих возможностей в том, что может показаться лучшим способом для выполнения задач.

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
    {
    }
}

Приведенный выше код завершается ошибкой со следующими ошибками компиляции:

ошибка CS1503: аргумент 1: невозможно преобразовать из Covariance.GenericClass в Covariance.GenericClass

ошибка CS1503: аргумент 1: невозможно преобразовать из Covariance.GenericClass в Covariance.GenericClass

Любая помощь / руководство или соответствующие ссылки будут высоко ценится. Еще раз извиняюсь, если это дублирующий вопрос. Благодарю вас!

1 ответ

Решение

Вы можете объявлять модификаторы дисперсии (in, out) только для универсальных интерфейсов, но не для типов. Поэтому одним из способов решения этой проблемы было бы объявить интерфейс для вашего GenericClass, как это:

interface IGenericClass<out TemplateClass> where TemplateClass : TestInterface {
    TemplateClass goo { get; }
}
class GenericClass<TemplateClass> : IGenericClass<TemplateClass> where TemplateClass : TestInterface
{
    public TemplateClass goo { get; }
}

А потом

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>());
    }
}
Другие вопросы по тегам