如何为 List创建新的通用项?

发布于 2024-11-04 09:34:02 字数 2089 浏览 1 评论 0原文

给定一个可能包含 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;
    }

谢谢。

Given a list of a possible 5 items, the method below will return a new list of exactly 5 items (adding more items if the original list has less than 5). This works fine, but now I need to refactor it so that it can handle a generic T list (one that will have the same properties of year and Cnt). How can I convert this method to take in a List and have it return a new List with 5 elements?

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

When I try to use List I eventually run into this section:

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

and I get an error...

Thanks!

For completeness:

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

Thanks you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

请别遗忘我 2024-11-11 09:34:12

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

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

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

例如:

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

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

For that to work for arbitrary T, you had two choices:

  • add a where T : SomeType constraint, where SomeType is either a base-class or (more likely and more versatile) an interface that declares the properties you need
  • switch to using dynamic (or reflection before 4.0) to access the properties

The first gives you compile-time safety, but requires some commonality between the T; the second demands no commonality, but is entirely runtime - no static-analysis checking.

For example:

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

And add where T : IRenameThis to the method signature (between te closing ) of the parameters and te opening { of the method body)

ペ泪落弦音 2024-11-11 09:34:12
static List<T> CreateFiveYearTemplate( int startYear 
                                      ,int endYear
                                      ,ObjectResult<T> result)
      where T : FiveYearComplex, new()
{
  ...
}
static List<T> CreateFiveYearTemplate( int startYear 
                                      ,int endYear
                                      ,ObjectResult<T> result)
      where T : FiveYearComplex, new()
{
  ...
}
書生途 2024-11-11 09:34:10

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

话虽如此,这个方法看起来不太通用,因为约束是 非常具体。为什么您想要使其通用?

You cannot easily convert your method to handle a generic list, because well your method is not generic. It requires for each item in the list to have properties Cnt and Year, for your method to be generic you have to add this constraint.

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

Also your method requires a default constructor, which is expressed as the constraint new() - so it could look like this:

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

Having said that this method doesn't look very generic, since the constraints are very specific. Why do you want to make it generic?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文