如何为list创建新的通用项

本文关键字:创建 list | 更新日期: 2023-09-27 17:53:59

给定一个可能有5个项目的列表,下面的方法将返回一个恰好有5个项目的新列表(如果原始列表少于5个,则添加更多的项目)。这工作得很好,但现在我需要重构它,以便它可以处理一个通用的T列表(具有相同属性的T)。我如何将此方法转换为接受列表并使其返回一个具有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;
    }

当我尝试使用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;
    }

谢谢你。

如何为list创建新的通用项

你不能轻易地将你的方法转换为处理泛型列表,因为你的方法不是泛型的。它要求列表中的每个项目都具有属性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;
}

已经说过这个方法看起来不是很通用,因为约束非常具体。为什么使其通用?

对于任意T,您有两个选择:

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

第一个提供了编译时安全性,但需要T;第二种不要求通用性,但完全是运行时的——没有静态分析检查。

例如:

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

并将where T : IRenameThis添加到方法签名中(在参数的结束)和方法体的开始{之间)

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