[英]Why can I use an anonymous collection initializer with a read-only auto-property while I can't use an object initializer
Consider the following class with a read-only (or getter-only) property ClientPermissions :考虑以下具有只读(或仅 getter)属性 ClientPermissions 的class :
internal class Client
{
public string? ClientId { get; set; }
public HashSet<string> ClientPermissions { get; } = new(StringComparer.Ordinal);
public HashSet<string> ClientTokens { get; set; } = new(StringComparer.Ordinal);
}
It seems I can't assign an object during construction to the read-only auto-property ClientPermissions while I can assign it values with an anonymous collection initializer似乎我无法在构造期间将 object 分配给只读自动属性 ClientPermissions,而我可以使用匿名集合初始化程序为其分配值
SO 5646285 gives a hint that for the object initializer the dotnet compiler actually compiles this into using object creation and then addition of the values. SO 5646285提示对于 object 初始化程序,dotnet 编译器实际上将其编译为使用 object 创建然后添加值。
Ok.. but why can I use an anonymous collection initializer than with this read-only auto-property?好的.. 但是为什么我可以使用匿名集合初始化程序而不是使用这个只读自动属性?
// Works - no complaints from compiler when I use collection initializer on read-only auto-property ClientPermissions
var sc1 = new Client() { ClientId = "c1", ClientPermissions = { "a1", "b1" }, ClientTokens = { "t1", "t2" } };
// Works - no complaints from compiler when I use collection initializer on read-only auto-property and object initializer on normal/full auto-property
var sc2 = new Client() { ClientId = "c2", ClientPermissions = { "a1", "b1" }, ClientTokens = new HashSet<string>{ "t1", "t2" } };
// DOES NOT COMPILE - Compiler complains with a CS0200: Property or indexer '...' cannot be assigned to -- it is readonly
// auto-initialize syntax
var sc3 = new Client() { ClientId = "c3", ClientPermissions = new HashSet<string> { "a1", "b1" }, ClientTokens = new HashSet<string> { "t1", "t2" } };
This is calling the Add
method on the object referenced by ClientPermissions
:这是在 ClientPermissions 引用的
ClientPermissions
上调用Add
方法:
ClientPermissions = { "a1", "b1" }
It is not assigning a new object to that property, hence why it is allowed.它没有为该属性分配新的 object,因此是允许的。
This, conversely, is invalid, because you cannot assign a new object to that property after construction:相反,这是无效的,因为您不能在构造后将新的 object 分配给该属性:
ClientPermissions = new HashSet { "a1", "b1" }
That hint you found is exactly the reason.你发现的那个提示正是原因。
If you use a collection initialiser on the right hand side of ClientPermissions =
, the setter of ClientPermissions
is not called, as the post you linked says.如果您在
ClientPermissions =
右侧使用集合初始化程序,则不会调用ClientPermissions
的设置器,如您链接的帖子所述。 The generated code is:生成的代码是:
Client client = new Client();
client.ClientId = "c3";
client.ClientPermissions.Add("a1");
client.ClientPermissions.Add("b1");
HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("t1");
hashSet.Add("t2");
client.ClientTokens = hashSet;
Whereas if you use = new HashSet<string> {... }
, then you are calling the setter of ClientPermissions
, because the thing after the =
(ie new HashSet<string> {... }
) is an expression.而如果您使用
= new HashSet<string> {... }
,那么您正在调用ClientPermissions
的设置器,因为=
之后的东西(即new HashSet<string> {... }
)是一个表达式。 Note that this expression also has a collection initialiser inside it, that is processed separately.请注意,此表达式内部还有一个集合初始化器,它是单独处理的。
Client client = new Client();
client.ClientId = "c3";
HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("a1");
hashSet.Add("b1");
client.ClientPermissions = hashSet; // setter called here!
HashSet<string> hashSet2 = new HashSet<string>();
hashSet2.Add("t1");
hashSet2.Add("t2");
client.ClientTokens = hashSet2;
Think of it like this: the ClientPermissions = new HashSet<string> {... }
case is treated like any other Property = expression
initialiser in an object initialiser.可以这样想:
ClientPermissions = new HashSet<string> {... }
案例被视为 object 初始化程序中的任何其他Property = expression
初始化程序。 On the other hand, the ClientPermissions = {... }
case is the "special" syntax that you can only do in object initialisers and it is where Add
is called, rather than assigning the RHS to the LHS.另一方面,
ClientPermissions = {... }
情况是您只能在 object 初始化程序中执行的“特殊”语法,它是调用Add
的地方,而不是将 RHS 分配给 LHS。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.