Список с несколькими объектами Generi c (проблема ковариации) - PullRequest
1 голос
/ 07 января 2020

Я пытался решить эту проблему и смотрел на подобные проблемы, но здесь не могу найти правильное решение.

Я использую класс Generi c для хранения конфигурации для экспорта

public class SpreadsheetConfiguration<T> where T : class 
{
    public IEnumerable<T> ExportData {get; set;}
    // More stuff here
}

У меня есть ситуация, когда мне нужен их список, который может быть не того же типа Например, вот так:

public byte[] ExportMultipleSheets(IEnumerable<SpreadsheetConfiguration<object>> toExport)

Но я не могу на всю жизнь выяснить, как сделать эту работу, и я рассмотрел другие маршруты выше в отношении создания ISpreadsehetConfiguration или иным образом.

Это для проекта OpenSource здесь: https://github.com/IowaComputerGurus/netcore.utilities.spreadsheet

Я знаю, что что-то упустил, но я пробовал все вышеперечисленное, но до сих пор не получаю до окончательного использования, где я все еще могу сделать

var toExport = new SpreadsheetConfiguration<MyOtherClass>();

Поскольку он не может преобразовать

1 Ответ

1 голос
/ 07 января 2020

Если ваш класс должен иметь установщик на этом IEnumerable<T>, то он не может быть ковариантным. Ковариация только для чтения, контравариация только для записи. Если вам нужны оба варианта, а также требуется набор таких конфигураций, тогда ваш дизайн имеет недостатки.

Если вы хотите иметь только get доступ к этому свойству, то сначала вам нужно создать интерфейс для вашего класс, так как дисперсия работает только на универсальных c интерфейсах:

public interface ISpreadsheetConfiguration<out T> where T : class
{
    IEnumerable<T> ExportData { get; }
}

public class SpreadsheetConfiguration<T> : ISpreadsheetConfiguration<T> where T : class
{
    public IEnumerable<T> ExportData {get; set;}
}

Обратите внимание на ключевое слово out в объявлении параметра типа интерфейса - это означает, что ISpreadsheetConfiguration<T> является ковариантным в T.

Теперь вы можете сделать это:

public byte[] ExportMultipleSheets(IEnumerable<ISpreadsheetConfiguration<object>> toExport);


var toExport = new ISpreadsheetConfiguration<object>[]
{
    new SpreadsheetConfiguration<MyOtherClass>(),
    new SpreadsheetConfiguration<CompletelyDifferentClass>()
};

ExportMultipleSheets(toExport);

Подробнее о дисперсии и о том, почему ковариация не может работать с типом, который разрешает как чтение, так и запись с типом T здесь .

...