c# 6为此增加了一个新特性:扩展Add方法。这在VB.net中一直是可能的,但现在在c#中是可用的。
现在你不必直接将add()方法添加到类中,你可以将它们作为扩展方法来实现。当使用Add()方法扩展任何可枚举类型时,您将能够在集合初始化表达式中使用它。所以你不必再显式地从列表中派生(正如在另一个答案中提到的那样),你可以简单地扩展它。
public static class TupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
T1 item1, T2 item2)
{
list.Add(Tuple.Create(item1, item2));
}
public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
T1 item1, T2 item2, T3 item3)
{
list.Add(Tuple.Create(item1, item2, item3));
}
// and so on...
}
这将允许您在任何实现IList<>的类上执行此操作:
var numbers = new List<Tuple<int, string>>
{
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
{ 0, 0, 0 },
{ 1, 2, 3 },
{ -4, -2, 42 },
};
当然,您不局限于扩展元组的集合,它可以用于您想要特殊语法的任何特定类型的集合。
public static class BigIntegerListExtensions
{
public static void Add(this IList<BigInteger> list,
params byte[] value)
{
list.Add(new BigInteger(value));
}
public static void Add(this IList<BigInteger> list,
string value)
{
list.Add(BigInteger.Parse(value));
}
}
var bigNumbers = new List<BigInteger>
{
new BigInteger(1), // constructor BigInteger(int)
2222222222L, // implicit operator BigInteger(long)
3333333333UL, // implicit operator BigInteger(ulong)
{ 4, 4, 4, 4, 4, 4, 4, 4 }, // extension Add(byte[])
"55555555555555555555555555555555555555", // extension Add(string)
};
c# 7将增加对语言内建的元组的支持,尽管它们是不同的类型(System。ValueTuple相反)。因此,为值元组添加重载是很好的,这样你也可以选择使用它们。不幸的是,在这两者之间没有定义隐式转换。
public static class ValueTupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}
这样列表初始化看起来会更好。
var points = new List<Tuple<int, int, int>>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};
但是,与其经历所有这些麻烦,不如改用专门使用ValueTuple。
var points = new List<(int, int, int)>
{
(0, 0, 0),
(1, 2, 3),
(-1, 12, -73),
};