Как создать новые общие элементы для списка <T>? - PullRequest
2 голосов
/ 02 мая 2011

Учитывая список из 5 возможных элементов, приведенный ниже метод вернет новый список из 5 элементов (добавление дополнительных элементов, если в исходном списке менее 5).Это работает нормально, но теперь мне нужно реорганизовать его, чтобы он мог обрабатывать общий список T (тот, который будет иметь те же свойства года и Cnt).Как я могу преобразовать этот метод в список и вернуть ему новый список с 5 элементами?

    private static List<FiveYearComplex> CreateFiveYearTemplate(int startYear, 
        int endYear, ObjectResult<FiveYearComplex> result)
    {
        var list = new List<FiveYearComplex>(5);

        for (int year = startYear; year < endYear; ++year)
        {
            list.Add(new FiveYearComplex() { Year = year, Cnt = 0 });
        }
        FiveYearComplex tmpItem;
        foreach (var item in result)
        {
            tmpItem = list.Find(w => w.Year == item.Year);
            if (tmpItem == null)
            {
                tmpItem = new FiveYearComplex() { Cnt = 0, Year = item.Year };
            }
            else
            {
                tmpItem.Cnt = item.Cnt;
            }
        }
        return list;
    }

Когда я пытаюсь использовать Список, я в итоге сталкиваюсь с этим разделом:

for (int year = startYear; year < endYear; ++year)
{
    list.Add(new T() { Year = year, Cnt = 0 });
}

и я получаю сообщение об ошибке ...

Спасибо!

За полноту:

    public interface IYearTemplate
    {
        int? Year { get; set; }
        decimal? Cnt { get; set; }
    }

    private static List<T> CreateFiveYearTemplate <T> (
        int startYear, int endYear, 
        ObjectResult<FiveYearAttendanceComplex> result) 
        where T : IYearTemplate, new()
    {
        var list = new List<T>(5);

        for (int year = startYear; year < endYear; ++year)
        {
            list.Add(new T() { Year = year, Cnt = 0 });
        }
        T tmpItem;
        foreach (var item in result)
        {
            tmpItem = list.Find(w => w.Year == item.Year);
            if (tmpItem == null)
            {
                tmpItem = new T() { Cnt = 0, Year = item.Year };
            }
            else
            {
                tmpItem.Cnt = item.Cnt;
            }
        }
        return list;
    }

Спасибо.

Ответы [ 3 ]

4 голосов
/ 02 мая 2011

Вы не можете легко конвертировать ваш метод для обработки общего списка, потому что ваш метод не является универсальным. Для каждого элемента в списке требуются свойства Cnt и Year, для того, чтобы ваш метод был универсальным, необходимо добавить это ограничение.

public interface IYearTemplate
{
   int Cnt {get;set;}
   int Year {get;set;}
}

Также вашему методу требуется конструктор по умолчанию, который выражается в виде ограничения new() - поэтому он может выглядеть следующим образом:

private static List<T> CreateFiveYearTemplate<T>(int startYear,
    int endYear, ObjectResult<T> result) where T: IYearTemplate, new()
{
    var list = new List<T>(5);

    for (int year = startYear; year < endYear; ++year)
    {
        list.Add(new T() { Year = year, Cnt = 0 });
    }
    T tmpItem;
    foreach (var item in result)
    {
        tmpItem = list.Find(w => w.Year == item.Year);
        if (tmpItem == null)
        {
            tmpItem = new T() { Cnt = 0, Year = item.Year };
        }
        else
        {
            tmpItem.Cnt = item.Cnt;
        }
    }
    return list;
}

Сказав, что этот метод не выглядит очень общим, так как ограничения очень специфичны . Почему вы хотите сделать его родовым?

3 голосов
/ 02 мая 2011

Чтобы это работало для произвольного T, у вас было два варианта:

  • добавить ограничение where T : SomeType, где SomeType является либо базовым классом, либо (более вероятным и универсальным) интерфейсом, который объявляет нужные вам свойства
  • переключиться на использование dynamic (или отражение до 4.0) для доступа к свойствам

Первый дает вам безопасность во время компиляции, но требует некоторого сходства между T; второе не требует общности, но полностью выполняется - нет статического анализа.

Например:

interface IRenameThis {
    int Year {get;set;}
    int Cnt {get;set;}
}

И добавить where T : IRenameThis к сигнатуре метода (между закрытием ) параметров и открытием { тела метода)

1 голос
/ 02 мая 2011
static List<T> CreateFiveYearTemplate( int startYear 
                                      ,int endYear
                                      ,ObjectResult<T> result)
      where T : FiveYearComplex, new()
{
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...