我有两个私有列表需要在创建对象时初始化。第二个列表取决于第一个列表。我可以这样做:
public class MyClass
{
private List<T> myList = new List<T>();
private ReadOnlyCollection<T> myReadOnlyList = myList.AsReadOnly;
...
}
第二个列表是第一个只读包装。
我可以期望c#每次运行时都按此顺序执行这两行吗?
或者我应该将这个初始化放在构造函数中吗?
修改
抱歉愚蠢的问题。我试过了,编译器说:
Error 1 A field initializer cannot reference the
non-static field, method, or property...
答案 0 :(得分:12)
没有。如果要基于类中的单独变量初始化变量,则需要在构造函数中执行此操作:
public class MyClass
{
private List<T> myList = new List<T>();
private ReadOnlyCollection<T> myReadOnlyList;
public MyClass()
{
myReadOnlyList = myList.AsReadOnly;
}
}
内联的初始化器总是在静态上下文中运行,这意味着您无法访问类中的成员变量。但是,在构造函数内部,您可以执行此操作。内联的初始值设定项将在构造函数之前发生,这就是我可以将列表初始化保留的原因。
答案 1 :(得分:4)
我可以期望c#每次运行时都按此顺序执行这两行吗?
是的,合法的实例变量初始化程序(见下文)按它们出现的顺序运行。我推荐你参阅规范的第10.11.2节:
这对应于在进入构造函数之后和直接调用直接基类构造函数之前立即执行的赋值序列。变量初始值设定项以它们出现在类声明中的文本顺序执行。
但是,字段初始值设定项不能像您一样引用非静态字段。您的代码不合法。这是规范的§10.5.5.2:
实例字段的变量初始值设定项无法引用正在创建的实例。因此,在变量初始化程序中引用它是一个编译时错误,因为变量初始化程序通过简单名称引用任何实例成员是编译时错误。
关于你的第二个问题:
或者我应该将这个初始化放在构造函数中吗?
根据以上所述,你别无选择。至少,您必须在构造函数中初始化myReadOnlyList
,因为它引用了实例字段myList
。为清楚起见,我会将两者放在构造函数中。
最后一点,在另一个问题上。即使以下情况也不合法:
public class MyClass {
private List<T> myList;public class MyClass
private ReadOnlyCollection<T> myReadOnlyList;
public MyClass() {
myList = new List<T>();
myReadOnlyList = myList.AsReadOnly;
}
这是因为您尚未将MyClass
声明为通用类。将public class MyClass
替换为public class MyClass<T>
。
答案 2 :(得分:1)
是的,您应该将myReadOnlyList的初始化放在构造函数中,但为了保持一致性,我的建议将两者放在构造函数中。