C# c中只读属性的对象初始值设定项#
如果你有这门课:C# c中只读属性的对象初始值设定项#,c#,projection,readonly,object-initializers,C#,Projection,Readonly,Object Initializers,如果你有这门课: class Foo { Bar Bar { get; } = new Bar(); } class Bar { string Prop {get; set; } } 可以使用对象初始化,如: var foo = new Foo { Bar = { Prop = "Hello World!" } } 如果你有课 class Foo2 { ICollection<Bar> Bars { get; } = new Lis
class Foo {
Bar Bar { get; } = new Bar();
}
class Bar {
string Prop {get; set; }
}
可以使用对象初始化,如:
var foo = new Foo {
Bar = { Prop = "Hello World!" }
}
如果你有课
class Foo2 {
ICollection<Bar> Bars { get; } = new List<Bar>();
}
但是,我想写一些
var items = new [] {"Hello", "World"};
var foo = new Foo2 {
Bars = { items.Select(s => new Bar { Prop = s }) }
}
但是,上面的代码不使用以下代码编译:
无法将IEnumerable分配给Bar
我不能写:
var foo = new Foo2 {
Bars = items.Select(s => new Bar { Prop = s })
}
属性栏是只读的
这可以存档吗?
bar={…}
不执行赋值。相反,它为初始值设定项中的每个项调用Add
。这就是它不起作用的原因
这就是为什么Bar=items.Select(s=>newbar{Prop=s})
会给出相同的错误:它是一个赋值,而不是要添加的列表
除了使用构造函数传递值,或者在构造函数运行后使用常规的
Add
或AddRange
语句之外,没有其他选项。bar={…}
不会进行赋值。相反,它为初始值设定项中的每个项调用Add
。这就是它不起作用的原因
这就是为什么Bar=items.Select(s=>newbar{Prop=s})
会给出相同的错误:它是一个赋值,而不是要添加的列表
除了使用构造函数传递值,或者在构造函数运行后使用常规的Add
或AddRange
语句之外,没有其他选项。如果阅读实际的编译器错误(),您会发现集合初始值设定项对于Add()
调用来说只是语法上的糖分:
CS1950:最佳重载集合初始化器方法System.Collections.Generic.ICollection.Add(Bar)
具有一些无效参数
CS1503:参数#1
无法将系统.Collections.Generic.IEnumerable
表达式转换为类型条形图
因此语法SomeCollection={someItem}
将被编译为SomeCollection.Add(someItem)
。您不能将IEnumerable
添加到Bar
s的集合中
您需要手动添加所有项目:
foreach (bar in items.Select(s => new Bar { Prop = s }))
{
foo.Bars.Add(bar);
}
或者,如果您的目标是较短的代码,请在Foo2
的构造函数中执行相同的操作:
public class Foo2
{
public ICollection<Bar> Bars { get; }
public Foo2() : this(Enumerable.Empty<Bar>()) { }
public Foo2(IEnumerable<Bar> bars)
{
Bars = new List<Bar>(bars);
}
}
对于@jeroenmoster所设想的对集合初始值设定项语法的有趣滥用,您可以使用扩展方法:
public static class ICollectionExtensions
{
public static void Add<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
公共静态类ICollectionExtensions
{
公共静态无效添加(此ICollection集合,IEnumerable items)
{
foreach(项目中的var项目)
{
集合。添加(项目);
}
}
}
这使得:
public class Foo
{
public ICollection<string> Bar { get; } = new List<string>();
}
var foo = new Foo
{
Bar = { new [] { "foo", "bar", "baz" } }
};
公共类Foo
{
公共ICollection条{get;}=new List();
}
var foo=新foo
{
Bar={new[]{“foo”,“Bar”,“baz”}
};
但是这太糟糕了。如果您阅读实际的编译器错误(),您会发现集合初始值设定项对于Add()
调用来说只是语法上的糖分:
CS1950:最佳重载集合初始化器方法System.Collections.Generic.ICollection.Add(Bar)
具有一些无效参数
CS1503:参数#1
无法将系统.Collections.Generic.IEnumerable
表达式转换为类型条形图
因此语法SomeCollection={someItem}
将被编译为SomeCollection.Add(someItem)
。您不能将IEnumerable
添加到Bar
s的集合中
您需要手动添加所有项目:
foreach (bar in items.Select(s => new Bar { Prop = s }))
{
foo.Bars.Add(bar);
}
或者,如果您的目标是较短的代码,请在Foo2
的构造函数中执行相同的操作:
public class Foo2
{
public ICollection<Bar> Bars { get; }
public Foo2() : this(Enumerable.Empty<Bar>()) { }
public Foo2(IEnumerable<Bar> bars)
{
Bars = new List<Bar>(bars);
}
}
对于@jeroenmoster所设想的对集合初始值设定项语法的有趣滥用,您可以使用扩展方法:
public static class ICollectionExtensions
{
public static void Add<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
公共静态类ICollectionExtensions
{
公共静态无效添加(此ICollection集合,IEnumerable items)
{
foreach(项目中的var项目)
{
集合。添加(项目);
}
}
}
这使得:
public class Foo
{
public ICollection<string> Bar { get; } = new List<string>();
}
var foo = new Foo
{
Bar = { new [] { "foo", "bar", "baz" } }
};
公共类Foo
{
公共ICollection条{get;}=new List();
}
var foo=新foo
{
Bar={new[]{“foo”,“Bar”,“baz”}
};
汉斯·帕桑特:这将给出一个无法分配给酒吧的列表。你必须走很长的路,调用
酒吧。如果你只有ICollection
,那么为每个项目添加。对象初始值设定项只是语法速记;C#通常对添加会增加运行时开销的语法持谨慎态度,并且更希望您能够明确地说明这一点(当然,这也有例外)。@Flater对我来说似乎是正确的。你认为哪一个是错的?@Diegrafaelsouza不,它是只读的。太多的语法糖会导致语言衰退。Foo2需要一个构造函数,这样您就可以初始化条。@Hans Passant:这将给出无法分配给条的列表。您必须走很长的路,调用条。如果您只有ICollection
,请为每个项添加。对象初始值设定项只是语法速记;C#通常对添加会增加运行时开销的语法持谨慎态度,并且更希望您能够明确地说明这一点(当然,这也有例外)。@Flater对我来说似乎是正确的。你认为哪一个是错的?@Diegrafaelsouza不,它是只读的。太多的语法糖会导致语言衰退。Foo2需要一个构造函数,这样你就可以初始化条了。不,如果条不是只读的,第二个就可以了。它失败是因为它是只读的。我想添加选择器中的每一项。换句话说,这就是我所说的。因为它是赋值,所以属性不能是只读的。所以不要赋值,而是调用Add
。@MichaWiedenmann:这是一个常规的对象初始值设定项,而不是集合初始值设定项。语法Bar={Prop=…}
与Bar={Prop}
不同,尽管表面上相似。对于对象初始值设定项来说,Bar
是否为只读并不重要,只要Prop
是可写的——它不指定新的Bar
。这是在中记录的,因此应该