查看扩展列表<>功能

时间:2011-05-27 13:08:33

标签: c# refactoring

我很好奇我是否可以增强标准的通用List<>功能,因为我厌倦了编写代码,如:

var list = new List<Person>{
     new Person{Name = "David", Age = 24},
     new Person{Name = "John", Age = 30}
 };
list.Add(new Person{Name = "Terry", Age = 28});

我希望隐式构建T。我想出的最好的东西允许我用最多四个对象构造参数来做这个:

  var list = new ListWithConstructor<string, int, Person>(
                (name,age) => new Person { Name = name, Age = age })
  {
       {"David", 24},
       {"John", 30}
  };          
  list.Add("Terry", 28);

这是这样实现的:

public class ListWithConstructor<T1, T> : List<T>
{
    private readonly Func<T1, T> itemConstructor;
    public ListWithConstructor(Func<T1, T> itemConstructor)
    {
        this.itemConstructor = itemConstructor;
    }

    public void Add(T1 arg1)
    {
        base.Add(itemConstructor(arg1));
    }
}

public class ListWithConstructor<T1, T2, T> : List<T>
{
    private readonly Func<T1, T2, T> itemConstructor;
    public ListWithConstructor(Func<T1, T2, T> itemConstructor)
    {
        this.itemConstructor = itemConstructor;
    }

    public void Add(T1 arg1, T2 arg2)
    {
        base.Add(itemConstructor(arg1, arg2));
    }
}

......等等最多四个参数。

显然,其他List<>构造函数(获取容量和IEnumerable现有元素)也可以实现。

如何改进?

2 个答案:

答案 0 :(得分:1)

您正在寻找的功能(几乎)已经触手可及:

var names = new[] { "David", "John" };
var persons = new List<Person>(names.Select(name => new Person { Name = name }));

通过这种方式,您也可以清楚地分离关注点; List完全不参与对象构造(甚至不是仅通过调用委托),而是简单地分配了一系列对象。转换是分开处理的。

这也可以处理将多个值转换为单个对象的情况:

public static IList<Person> GetListFromNamesAndAges(string[] names, int[] ages)
{
    if (names.Length != ages.Length)
    {
        throw new ArgumentException("names and ages must be of equal length.");
    }

    return new List<Person>(
        names.Select((name, index) =>
            new Person { Name = name, Age = ages[index] }));
}

// usage example:
var persons = GetListFromNamesAndAges(
    new[] {"David", "John"}, 
    new[] {24, 30});

如果将两个列表中的值合并为单个对象,则使用Zip可能会提供稍微清晰的代码;

return names
    .Zip(ages, (name, age) => new Person {Name = name, Age = age})
    .ToList();

答案 1 :(得分:0)

你不应该这样做。您违反了“关注分离”原则 为什么不为具有一个构造函数参数的情况声明从stringPerson的隐式转换?

public class Person
{
    public Person(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    public static implicit operator Person(string name)
    {
        return new Person(name);
    }
}

var list = new List<Person>();
list.Add("Terry");

为了能够缩短添加具有多个构造函数参数的对象的代码,我认为您应该执行以下操作:
Func

的调用中直接使用您创建的Add
Func<string, string, Person> ctor = 
    (firstName, name) => new Person { Name = name, FirstName = firstName };
list.Add(ctor("Terry", "McDouglas"));
list.Add(ctor("Jones", "Miller"));

很多更清洁。