属性 赋值
Property value assignment
我不明白为什么代码的 first 块是 valid 而 latter:
var e = new Exception()
{
Data =
{
{"a","a"}
}
};
此处出现编译时错误:
e.Data =
{
{"a","a"}
};
嗯Data
属性已经declared为readonly属性:
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
Error CS0200 Property or indexer 'Exception.Data' cannot be assigned to -- it is read only (bold is mine, Dmitry Bychenko)
请注意,您只需 添加 项所需的项目到 Data
:
Exception e = new Exception();
// Add {"a", "a"} to existing Data
e.Data.Add("a", "a");
其他答案并非 100% 准确。是的,Data
是只读的 属性。但是,只读(即 getter-only)属性 可以 only 赋予 initial/default 值(在这种情况下,该值被分配到编译器生成的支持字段),但它 不能 分配给;时期。不在对象初始值设定项中,不在构造函数中,也不在其他任何地方。
请注意,另一方面,readonly fields 可以在构造函数中赋值。
为了分配给 属性,它 必须 有一个 setter(例如,set;
、private set;
等),如果您使用的是 C# 9.0 或更高版本,则可以使用 init-only setter(即 init;
),这将允许您在对象初始值设定项中分配给 属性但在那之后就没有了。
只要 属性 没有 setter,您永远无法 直接 更改其值。为了证明这一点,尝试在对象初始值设定项中将 Data
设置为 null
:
var e = new Exception()
{
Data = null // Nope, compiler won't allow it because Data is readonly
};
那么,为什么它在第一个块中起作用?
那是因为您正在使用 Collection Initializer. When you do that, the compiler doesn't actually assign a value to the property. Instead, it calls the Add()
method. You can see this for yourself here 初始化 Data
。第一个(即工作)块由编译器翻译为:
Exception e = new Exception();
e.Data.Add("a", "a"); // <-- Ah! `Data` was never assigned to.
.. 顺便说一下,通常 会抛出一个 NullReferenceException(因为我们在 属性 上调用 Add()
方法应该为空)。但是,如果您查看 Exception.Data
的 source code,您会发现其支持字段始终在 getter 中初始化,因此它永远不会为空:
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;
}
}
您不能分配数据,因为数据是字典。如果新字典对象具有 setter,您可以对其进行赋值,但数据只有 getter,并且它在 init
上创建为空集合
public class ABC
{
public virtual System.Collections.IDictionary Data { get; } = new Dictionary<object,object> ();
}
你只能通过一些数据初始化它,就像使用集合初始化程序的任何其他集合一样
var abc = new ABC()
{
Data = {
{"a","a"}
}
};
或通过两种常用方式添加新条目,与使用任何其他词典相同
abc.Data["c"] = "c";
//or
abc.Data.Add("d", "d");
}
我不明白为什么代码的 first 块是 valid 而 latter:
var e = new Exception()
{
Data =
{
{"a","a"}
}
};
此处出现编译时错误:
e.Data =
{
{"a","a"}
};
嗯Data
属性已经declared为readonly属性:
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
Error CS0200 Property or indexer 'Exception.Data' cannot be assigned to -- it is read only (bold is mine, Dmitry Bychenko)
请注意,您只需 添加 项所需的项目到 Data
:
Exception e = new Exception();
// Add {"a", "a"} to existing Data
e.Data.Add("a", "a");
其他答案并非 100% 准确。是的,Data
是只读的 属性。但是,只读(即 getter-only)属性 可以 only 赋予 initial/default 值(在这种情况下,该值被分配到编译器生成的支持字段),但它 不能 分配给;时期。不在对象初始值设定项中,不在构造函数中,也不在其他任何地方。
请注意,另一方面,readonly fields 可以在构造函数中赋值。
为了分配给 属性,它 必须 有一个 setter(例如,set;
、private set;
等),如果您使用的是 C# 9.0 或更高版本,则可以使用 init-only setter(即 init;
),这将允许您在对象初始值设定项中分配给 属性但在那之后就没有了。
只要 属性 没有 setter,您永远无法 直接 更改其值。为了证明这一点,尝试在对象初始值设定项中将 Data
设置为 null
:
var e = new Exception()
{
Data = null // Nope, compiler won't allow it because Data is readonly
};
那么,为什么它在第一个块中起作用?
那是因为您正在使用 Collection Initializer. When you do that, the compiler doesn't actually assign a value to the property. Instead, it calls the Add()
method. You can see this for yourself here 初始化 Data
。第一个(即工作)块由编译器翻译为:
Exception e = new Exception();
e.Data.Add("a", "a"); // <-- Ah! `Data` was never assigned to.
.. 顺便说一下,通常 会抛出一个 NullReferenceException(因为我们在 属性 上调用 Add()
方法应该为空)。但是,如果您查看 Exception.Data
的 source code,您会发现其支持字段始终在 getter 中初始化,因此它永远不会为空:
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; } }
您不能分配数据,因为数据是字典。如果新字典对象具有 setter,您可以对其进行赋值,但数据只有 getter,并且它在 init
上创建为空集合public class ABC
{
public virtual System.Collections.IDictionary Data { get; } = new Dictionary<object,object> ();
}
你只能通过一些数据初始化它,就像使用集合初始化程序的任何其他集合一样
var abc = new ABC()
{
Data = {
{"a","a"}
}
};
或通过两种常用方式添加新条目,与使用任何其他词典相同
abc.Data["c"] = "c";
//or
abc.Data.Add("d", "d");
}