Компилятору C# не удается распознать, что класс реализует интерфейс

Следующему коду не удается скомпилировать (использующий VS2010), и я не вижу почему. Компилятор должен смочь вывести это List<TestClass> 'совместимо' (извините из-за отсутствия лучшего слова) с IEnumerable<ITest>, но так или иначе это не делает. Что я пропускаю здесь?


interface ITest {
    void Test();
}


class TestClass : ITest {
    public void Test() {
    }
}

class Program {
    static void Test(IEnumerable<ITest> tests) {
        foreach(var t in tests) {
            Console.WriteLine(t);
        }
    }
    static void Main(string[] args) {
        var lst = new List<TestClass>();

        Test(lst); // fails, why?

        Test(lst.Select(t=>t as ITest)); //success

        Test(lst.ToArray()); // success
    }
}

Компилятор дает две ошибки:

  1. Лучший перегруженный метод соответствует для 'ConsoleApplication1. Программа. Тест (Система. Наборы. Универсальный. IEnumerable <ConsoleApplication2. ITest>)', имеет некоторые недействительные аргументы

  2. Аргумент 1: не может преобразовать из 'Системы. Наборы. Универсальный. Список <ConsoleApplication2. TestClass>' к 'Системе. Наборы. Универсальный. IEnumerable <ConsoleApplication2. ITest>'

12
задан Simon P Stevens 20 May 2010 в 09:22
поделиться

3 ответа

То, что вы пытаетесь сделать, называется ковариацией - преобразование из более узкого типа (TestClass) в более широкий тип (ITest). Это то, к чему вы будете постоянно привыкать, это происходит, например, когда вы конвертируете из числа с плавающей запятой в двойное.

К сожалению .Net 3.5 и ниже не поддерживает ковариацию в общих классах.

.Net 4.0 теперь поддерживает ковариацию (и контравариантность) в универсальных типах, при условии, что эти универсальные классы скомпилированы с ключевыми словами out для ковариантных типов и в для контравариантных типов. IEnumerable в .Net 4.0 определяется как ковариантный. Если вы щелкните правой кнопкой мыши тип IEnumerable и выберите «перейти к определению», вы увидите следующее:

public interface IEnumerable<out T> : IEnumerable

Если вы используете VS2010, вам нужно будет убедиться, что ваш проект нацелен на .net 4.0. Это можно изменить в свойствах проекта. Щелкните правой кнопкой мыши проект, выберите свойства, перейдите на вкладку «Приложение» и убедитесь, что «Целевая платформа» соответствует .Net 4.

MSDN содержит дополнительную информацию .

8
ответ дан 2 December 2019 в 22:04
поделиться

Это связано с дисперсией (ковариацией и контравариацией); посмотрите этот пост и ответ Jon Skeet

2
ответ дан 2 December 2019 в 22:04
поделиться

Проверьте целевую версию платформы для вашего проекта. Этот код будет работать только в .NET 4.

1
ответ дан 2 December 2019 в 22:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: