对自定义类型使用集合初始值设定项语法
本文关键字:语法 类型 自定义 集合 | 更新日期: 2023-09-27 18:23:58
我有一个很大的静态列表,它基本上是一个查找表,所以我在代码中初始化了该表。
private class MyClass
{
private class LookupItem
{
public int Param1 { get; set; }
public int Param2 { get; set; }
public float Param2 { get; set; }
public float Param4 { get; set; }
}
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem() { Param1 = 1, Param2 = 2, Param3 = 3 Param4 = 4 },
new LookupItem() { Param1 = 5, Param2 = 6, Param3 = 7 Param4 = 8 },
//etc
}
}
真正的LookupItem
有更多的属性,所以我添加了一个构造函数来实现更紧凑的初始化格式:
private class MyClass
{
private class LookupItem
{
public int Param1 { get; set; }
public int Param2 { get; set; }
public float Param2 { get; set; }
public float Param4 { get; set; }
public LookupItem(int param1, int param2, float param3, float param4)
{
Param1 = param1;
Param2 = param2;
Param3 = param3;
Param4 = param4;
}
}
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem(1, 2, 3, 4),
new LookupItem(5, 6, 7, 8),
//etc
}
}
我真正想做的是为对象本身使用集合初始化器格式,这样我就可以去掉每一行上的new LookupItem()
。例如:
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
//etc
}
这可能吗?我认为这是因为Dictionary<>
的KeyValuePair
可以用这种方式初始化。
MSDN状态:
集合初始值设定项允许您指定一个或多个元素初始化实现IEnumerable。元素初始值设定项可以是一个简单的值表达式或对象初始值设定项。通过使用集合初始值设定项不必指定对的Add方法的多次调用类;编译器添加调用。
这是否意味着我需要在LookupItem
类上实现IEnumerable
并返回每个参数?不过,我的课不是集合课。
我认为您需要制作一个自定义集合,而不是List。例如,将其称为LookupItemTable。给该集合一个Add(int,int,float,float)方法,并让它实现IEnumerable。例如:
class LookupItem
{
public int a;
public int b;
public float c;
public float d;
}
class LookupItemTable : List<LookupItem>
{
public void Add(int a, int b, float c, float d)
{
LookupItem item = new LookupItem();
item.a = a;
item.b = b;
item.c = c;
item.d = d;
Add(item);
}
}
private static LookupItemTable _lookupTable = new LookupItemTable {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 }
};
我现在已经尝试了上面的代码,它似乎对我有效。
快速修复:使用接受多个参数的Add
重载创建自己的List
类型:
class LookupList : List<LookupItem> {
public void Add(int Param1, int Param2, ... sometype ParamX) {
this.Add(new LookupItem() { Param1 = Param1, Param2 = Param2, ... ParamX = ParamX });
}
}
现在可以随心所欲地工作:
private static LookupList _lookupTable = new LookupList() {
{1,2,3,4},
{2,7,6,3}
};
更基本的答案:
您混淆了对象初始化器和集合初始化器。简单地说:
对象初始值设定项是一种语法技巧,它在后台使用指定的值为每个命名属性调用属性集方法。
集合初始值设定项是一种语法技巧,在后台:
- 对于
Array
类型:用项填充数组 - 对于必须实现
IEnumerable
的任何其他类型:为每个子方括号集合调用Add
方法
这就是所有。例如,考虑以下黑客:
public class Hack : IEnumerable {
public int LuckyNumber { get; set; }
public double Total { get; private set; }
public void Add(string message, int operand1, double operand2, double operand3) {
Console.WriteLine(message);
this.Total += operand1 * operand2 - operand3;
}
public IEnumerator GetEnumerator() { throw new NotImplementedException(); }
}
class Program {
static void Main(string[] args) {
Hack h1 = new Hack() {
{ "Hello", 1, 3, 2},
{ "World", 2, 7, 2.9}
};
Console.WriteLine(h1.Total);
Hack h2 = new Hack() { LuckyNumber = 42 };
Console.WriteLine(h2.LuckyNumber);
}
}
您永远不应该在真实的程序中这样做,但我希望检查这个例子和结果,特别是如果您对它进行调试,将有助于您清楚地理解初始化程序,并为当前场景选择一个好的解决方案。
您试图在列表本身上使用集合初始值设定项,而不是在您的类型上:
// Note the "new List<...>" part - that specifies what type the collection
// initializer looks at...
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
}
所以它正在寻找一个在List<T>
上有四个参数的Add
方法,但这并不存在。
您必须实现自己的集合类才能使用自定义集合初始值设定项。当您使用List<T>
时,您会遇到构造函数调用的问题。
与其用从List<LookupItem>,添加一个调用所需构造函数的简单扩展:
public static class LookupItemListExtensions
{
public static void Add(this List<LookupItem> lookupItemList, int param1, int param2, float param3, float param4)
{
lookupItemList.Add(new LookupItem(param1, param2, param3, param4));
}
}
请注意,你是在用清晰换取简洁,所以使用的风险自负。使用"new ListItem"可以直接对构造函数执行F12;这个扩展没有(对其他开发人员来说也不太可能是显而易见的)。
这是否意味着我需要在LookupItem类上实现IEnumerable并返回每个参数?不过,我的课不是集合课。
不,这意味着List<LookupItem>
实现了IEnumerable
,这就是为什么你可以写
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem(1, 2, 3, 4),
new LookupItem(5, 6, 7, 8),
//etc
}
这也意味着,如果您的LookupItem
是实现IEnumerable
的集合,那么您可以编写:
private static List<LookupItem> _lookupTable = new List<LookupItem>()
{
new LookupItem { new Item(), new Item() },
new LookupItem { new Item(), new Item() }
}