简体   繁体   English

为什么我可以使用具有只读自动属性的匿名集合初始化程序,而我不能使用 object 初始化程序

[英]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" }

The relevant documentation is here .相关文档在这里

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.

相关问题 简单类型的只读自动属性:初始化程序VS表达式主体获取器 - Read-Only Auto-Property for Simple Types: Initializer VS Expression Body Getter 我可以为属性使用集合初始值设定项吗? - Can I use a collection initializer for an Attribute? 为什么我不能将数组初始值设定项与隐式类型变量一起使用? - Why can't I use the array initializer with an implicitly typed variable? 我可以使用带有 LINQ 的集合初始化程序来返回完全填充的集合吗? - Can I use a collection initializer with LINQ to return a fully populated collection? 我可以为Dictionary <TKey,TValue>条目使用集合初始值设定项吗? - Can I use a collection initializer for Dictionary<TKey, TValue> entries? 如何在 ExpandoObject 中使用集合初始值设定项语法? - How can I use collection initializer syntax with ExpandoObject? 我可以在构造对象之外使用对象初始化程序吗? - Can I use object initializer outside construction of an object? 为什么我可以使用具有来自另一个类的私有集合访问权限的集合初始值设定项? - Why can I use a collection initializer with private set access from another class? 自动属性初始化器Singleton实现 - Auto-property initializer Singleton implementation 具有初始化程序引用实例成员的自动属性 - Auto-property with initializer referencing instance member
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM