如何为List <t>创建新的通用项?</t>

时间:2011-05-01 20:10:48

标签: c# generics .net-4.0 refactoring

给出可能的5个项目的列表,下面的方法将返回一个恰好5个项目的新列表(如果原始列表少于5个,则添加更多项目)。这工作正常,但现在我需要重构它,以便它可以处理一个通用的T列表(一个具有相同的年和Cnt属性)。如何将此方法转换为List并让它返回一个包含5个元素的新List?

    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;
    }

当我尝试使用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 个答案:

答案 0 :(得分:4)

您无法轻松转换您的方法来处理通用列表,因为您的方法不是通用的。它要求列表中的每个项目都具有属性CntYear,因为您的方法是通用的,您必须添加此约束。

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;
}

说过这个方法看起来不太通用,因为约束是非常具体的。为什么希望使其成为通用的?

答案 1 :(得分:3)

为了适用于任意T,您有两种选择:

  • 添加where T : SomeType约束,其中SomeType是基类或(更可能更通用)的接口,用于声明所需的属性
  • 切换到使用dynamic(或4.0之前的反射)来访问属性

第一个给你编译时安全性,但需要T之间的一些共性;第二个要求没有共性,但完全是运行时 - 没有静态分析检查。

例如:

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

where T : IRenameThis添加到方法签名中(在关闭参数)之间和方法正文的开放{之间)

答案 2 :(得分:1)

static List<T> CreateFiveYearTemplate( int startYear 
                                      ,int endYear
                                      ,ObjectResult<T> result)
      where T : FiveYearComplex, new()
{
  ...
}
相关问题