繁体   English   中英

属性值赋值

[英]Property value assignment

我不明白为什么代码的一块是有效的,但不是后者

var e = new Exception()
{
    Data =
    {
        {"a","a"}
    }
};

这里的编译时错误:

e.Data =
{
    {"a","a"}
};

Well Data属性已被声明只读属性:

public virtual System.Collections.IDictionary Data { get; }

这就是为什么你可以初始化它(即在构造函数中设置)

  // Create an instance, initialize `Data` with { "a", "a" }
  Exception e = new Exception() {
    Data = { { "a", "a" } }
  };

但你不能设置它:

 // Trying to set Data as { { "a", "a" } };
 e.Data = { { "a", "a" } }; // <- Compile time error here

错误 CS0200 无法将属性或索引器“Exception.Data”分配给 - 它是只读的(粗体是我的,Dmitry Bychenko)

请注意,您可以所需项目添加到Data中:

  Exception e = new Exception();

  // Add {"a", "a"} to existing Data
  e.Data.Add("a", "a"); 

另一个答案不是 100% 准确。 是的, Data是只读属性。 但是,只读(即,仅 getter)属性只能被赋予初始/默认值(在这种情况下,该值被分配给编译器生成的支持字段),但不能被分配给; 时期。 不在 object 初始化程序中,不在构造函数中,也不在其他任何地方。

请注意,另一方面,可以在构造函数中分配只读字段

为了分配给一个属性,它必须有一个 setter(例如set;private set;等),如果您使用 C# 9.0 或更高版本,您可以使用仅 init 的 setter (即init; ) 这将允许您分配给 object 初始化程序中的属性,但之后不能。

只要该属性没有设置器,就永远无法直接更改其值。 为了证明这一点,请尝试在 object 初始化程序中将Data设置为null

var e = new Exception()
{
    Data = null  // Nope, compiler won't allow it because Data is readonly
};

那么,为什么它在第一个块中起作用?

那是因为您正在使用Collection Initializer初始化Data 当你这样做时,编译器实际上并没有为属性赋值。 相反,它调用Add()方法。 您可以在此处亲自查看。 第一个(即工作)块由编译器翻译成:

Exception e = new Exception();
e.Data.Add("a", "a"); // <-- Ah! `Data` was never assigned to.

..顺便说一下,通常会抛出 NullReferenceException (因为我们在应该为 null 的属性上调用Add()方法)。 但是,如果您查看Exception.Data源代码,您会发现它的支持字段始终在 getter 中初始化,因此它永远不会是 null:

public virtual IDictionary Data { 
    [System.Security.SecuritySafeCritical]  // auto-generated
    get {
        if (_data == null)
            if (IsImmutableAgileException(this))
                _data = new EmptyReadOnlyDictionaryInternal();
            else
                _data = new ListDictionaryInternal();
        
        return _data;
    }
}

您不能分配数据,因为 Data 是字典。 如果新字典 object 有一个 setter,则可以分配它,但 Data 只有一个 getter,它在初始化时创建为空集合

public class ABC
{
 public virtual System.Collections.IDictionary Data { get; } =  new Dictionary<object,object> ();
}

你只能通过一些数据来初始化它,就像使用 Collection Initializer 的任何其他集合一样

    var abc = new ABC()
    {
        Data = {
        {"a","a"}
       }
    };

或通过两种常用方式添加新项目,就像您使用任何其他字典一样

    abc.Data["c"] = "c";
    //or 
    abc.Data.Add("d", "d");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM