C # Дженерики и вывод типа

#c# #.net #generics

#c# #.net #дженерики

Вопрос:

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

Это мой метод сохранения:

 public static void SaveList<T>(List<T> listToSave)
{
    foreach (T listItem in listToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}
  

Я получаю волнистую красную строку при сохранении и ошибку «Тип T должен быть ссылочным типом, чтобы использовать его в качестве параметра T»

Это мой метод загрузки:

     public static List<T> LoadList<T>()
    {
        List<T> list = (from index in DatabaseInstance.Query<T, int>() select index.Key).ToList();

        return list;
    }
  

Я получаю ту же ошибку.

Есть идеи?

Приветствия

Стив

Обновить:

Я добавил класс where T:, как было предложено, и получил сообщение об ошибке:

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

Следуя инструкциям в ссылке, предоставленной Брайаном, я добавил new() в конце, и теперь все работает.

Ответ №1:

Вам нужно ограничение универсального типа для вашего определения:

 public static void SaveList<T>(List<T> listToSave) where T : class
{
    foreach (T listItem in listToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}

public static List<T> LoadList<T>()  where T : class
{
    List<T> list = (from index in DatabaseInstance.Query<T, int>() select index.Key).ToList();
    return list;
}
  

Комментарии:

1. Выбрано в качестве ответа из-за ссылки на информацию об ограничении общего типа, которая помогла с дальнейшими ошибками.

Ответ №2:

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

 public static void SaveList<T>(IEnumerable<T> itemsToSave) where T : class
{
    foreach (T item in itemsToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}

public static IEnumerable<T> LoadList<T>() where T : class
{
    return (from index in DatabaseInstance.Query<T, int>()
            select index.Key);
}
  

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

Комментарии:

1. Эти два метода заслуживают переименования. Может SaveItems быть, и GetItems ?

Ответ №3:

Проблема в том, что в вашем существующем коде T может быть чем угодно. Это не нормально, потому Save что функция принимает только ссылочные типы.

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

 public static void SaveList<T>(List<T> listToSave) where T : class
{
    foreach (T listItem in listToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}
  

Ответ №4:

можете ли вы попробовать?

 public static void SaveList<T>(List<T> listToSave) where T:class
{
    foreach (T listItem in listToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}
  

Ответ №5:

Попробуйте добавить class ограничение:

 public static void SaveList<T>(List<T> listToSave) where T : class
{
    foreach (T listItem in listToSave)
    {
        DatabaseInstance.Save(listItem);
    }
}

public static List<T> LoadList<T>() where T : class
{
    List<T> list = (from index in DatabaseInstance.Query<T, int>()
            select index.Key).ToList();

    return list;
}