new List<BaseType>
{
new DerivedType
{
x="x1",y="y1",z="z1"
},
new DerivedType
{
x="x2",y="y2",z="z2"
},
new DerivedType
{
x="x3",y="y3",z="z3"
},
new DerivedType
{
x="x4",y="y4",z="z3"
},
...
}
在静态方法中,通过上面的方法初始化列表,我想知道是否有更好的方法在语法上做这个。
每次都以相同的顺序设置相同的字段,以便更容易。
答案 0 :(得分:8)
为什么不在这里使用for循环?
var list = new List<BaseType>(SomeValue);
for (int i = 1; i < SomeValue; i++) {
list.Add(new DerivedType {
x = string.Format("x{0}", i),
y = string.Format("y{0}", i),
z = string.Format("z{0}", i)
});
}
注意:我假设示例代码中的最后一个init应该有"z4"
而不是"z3"
答案 1 :(得分:5)
如果值实际上“x1”等,那么:
var list = Enumerable.Range(1, n)
.Select(i => new DerivedType {
x = "x" + i,
y = "y" + i,
z = "z" + i
})
.ToList<BaseType>();
这取决于C#4中的协方差。在C#3(或针对.NET 3.5)中,你需要类似的东西:
var list = Enumerable.Range(1, n)
.Select(i => (BaseType) new DerivedType {
x = "x" + i,
y = "y" + i,
z = "z" + i
})
.ToList();
或者如果那些只是样本值(或者即使它们不是),只需将构造函数添加到DerivedType
以允许您一次性传递三个属性将减少混乱:
new List<BaseType>
{
new DerivedType("x1", "y1", "z1"),
new DerivedType("x2", "y2", "z2"),
new DerivedType("x3", "y3", "z3"),
new DerivedType("x4", "y4", "z4"),
...
}
答案 2 :(得分:2)
您可以创建List<T>
的子类:
public class BaseTypeList : List<BaseType>
{
public void Add(string x, string y, string z)
{
Add(new DerivedType { x = x, y = y, z = z });
}
}
然后您可以更简洁地使用集合初始化程序语法:
new BaseTypeList
{
{ "x1", "y1", "z1" },
{ "x2", "y2", "z2" },
{ "x3", "y3", "z3" },
{ "x4", "y4", "z3" /* (sic) */ },
//...
}
这是有效的,因为编译器为集合初始化程序块中的每个元素执行单独的重载解析,查找具有与给定参数匹配的参数类型的Add方法。
如果你需要同类衍生类型,它会有点难看,但它是可能的:
public class BaseTypeList : List<BaseType>
{
public void Add(Type t, string x, string y, string z)
{
Add((BaseType)Activator.CreateInstance(t, x, y, z));
}
}
然后你会像这样初始化集合:
new BaseTypeList
{
{ typeof(DerivedType1), "x1", "y1", "z1" },
{ typeof(DerivedType1), "x2", "y2", "z2" },
{ typeof(DerivedType2), "x3", "y3", "z3" },
{ typeof(DerivedType2), "x4", "y4", "z3" /* (sic) */ },
//...
}
答案 3 :(得分:1)
使用NBuilder,您需要一行或两行代码(可以从NuGet获取):
List<BaseType> list = Builder<DerivedType>.CreateListOfSize(5).Build()
.ToList<BaseType>();
它使用值"xN"
"yN"
"zN"
(属性名称+元素索引)初始化所有属性。
答案 4 :(得分:1)
我觉得奇怪的是,没有人解决OP更普遍的问题,而是专注于该例子的人为特例。
正如所有重击手在这里所注意到的,对于这个例子的具体情况,正如Perl修道者可能会说的那样,“TMTOWTDI” - 有多种方法可以做到这一点。比其他人更好(或至少更简洁)。
在更一般的情况下,事情不是所有的单调序列,我认为没有更好的东西。你遇到了很多重复的样板。
C#没有像JSON或Javascript的对象初始化器那样的东西,或者C compound literals(2000年用C99引入),所有这些都为这类东西提供了更为简洁的语法。如果你问我,可惜。
这是一个想法,虽然有点丑陋的黑客:SCG.List<T>
和许多其他SCG
集合有一个构造函数重载接受IEnumerable<T>
,IDictionary<TKey,TValue>
或其他东西类似于正在构建的对象的填充。可以想象,可以将方式中所需的数据作为 embedded resource 以适合您的目的的格式嵌入。它甚至不必是一个嵌入式资源:一个简单的多行字符串文字,每个项目有一个逗号分隔的行就可以了。提供一个简单的工厂类或方法,使用该资源生成一个可以传递给IEnumerable
构造函数和Bob's-Yer-Uncle的LINQy List<T>
小部件流。
就像我说的,有点丑陋的黑客,但它会避免重复输入。
答案 5 :(得分:0)
我会用一个简单的数组来保存数据。然后使用此数组构建派生类型。请注意,数据值可能有些任意(此处显示的是字符串和int类型)。只需使用一个字符串数组就可以优化原始问题。
object[] data =
{
"x1", "y1", 4,
"x2", "y2", 3,
"x3", "y3", 2,
"x4", "y4", 3
};
int countPerType = 3;
int size = data.Length;
var initMe = new List<BaseType>();
for (int idx = 0; idx < size; idx += countPerType)
{
initMe.Add(
new DerivedType()
{
X = (string)data[idx],
Y = (string)data[idx + 1],
Z = (int)data[idx + 2]
});
}