C # Generics - знать, какой производный класс использовать в абстрактном методе - PullRequest
0 голосов
/ 09 мая 2018

Я работаю над проектом C # для разбора файлов разных типов.Для этого я создал следующую структуру классов:

interface FileType {}
    class FileType1 : FileType {}
    class FileType2 : FileType {}

abstract class FileProcessor {}
    class Processor_FileType1 : FileProcessor {} // Will use FileType1 - type of storage class
    class Processor_FileType2 : FileProcessor {} // Will use FileType2 - type of storage class

Итак, поскольку каждый FileProcessor использует различный тип FileType, я надеялся написать какой-то методв моем классе Base FileProcessor, чтобы иметь возможность получить значения из файла, выглядя примерно так:

abstract class FileProcessor 
{
    protected List<T> getValuesFromFile<T>() where T:FileType
    {
        try
        {
            otherClass.doProcess<T>();
        }
        catch (Exception ex)
        {
            throw new Exception("Unable to retrieve the data from the file.", ex);
        }
    }
}

И в другой библиотеке, которую я использовал (в связи с анализом файлов Excel), который я не могу изменить, у меня есть следующий метод:

        public List<T> doProcess<T>() where T : class, new()
        {
            // the actual work
        }

Но я получаю ошибку в моем методе getValuesFromFile, утверждая, что The type 'T' must be a reference Type, чтобы иметь возможность вернуть список в моем методе.

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

Есть ли способсделать это или это просто плохое программирование для Generics?

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Ваш otherClass.doProcess() метод объявлен как

public List<T> doProcess<T>() where T : class, new()

Таким образом, для этого T должен быть ссылочный тип и иметь конструктор по умолчанию без параметров .

В методе вызова вы только ограничили T для реализации интерфейса FileType:

List<T> getValuesFromFile<T>() where T:FileType

Этого недостаточно. Интерфейс также может быть реализован типом значения, и он ничего не говорит о конструкторах. Поэтому вам нужно изменить ограничения на:

List<T> getValuesFromFile<T>() where T: class, FileType, new()

(Обратите внимание, что ограничение class должно быть первым в объявлении ограничения).

0 голосов
/ 09 мая 2018

Вы можете убедиться, что T является ссылочным типом, ограничив его как:

where T : class, FileType

Мне трудно точно понять, что вы пытаетесь сделать, поэтому я не могу дать рекомендации по использованию вами дженериков в более общем плане.

...