查看扩展列表<>;功能

本文关键字:gt 功能 lt 扩展 列表 | 更新日期: 2023-09-27 17:57:44

我很好奇是否可以增强标准的通用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)也可以实现。

如何改进?

查看扩展列表<>;功能

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

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();

你不应该这样做。你违反了"关注点分离"原则
为什么不为带有一个构造函数参数的情况声明一个从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");

为了能够缩短添加具有多个构造函数参数的对象的代码,我认为您应该执行以下操作:
使用您在对Add:的调用中直接创建的Func

Func<string, string, Person> ctor = 
    (firstName, name) => new Person { Name = name, FirstName = firstName };
list.Add(ctor("Terry", "McDouglas"));
list.Add(ctor("Jones", "Miller"));

这是很多清洁。