[英]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.