假设我们有以下简单的类。请注意,唯一字段是readonly
,是ImmutableList<int>
的字段:
class Abc
{
readonly ImmutableList<int> elts;
public Abc(params int[] ls) => elts = ImmutableList.CreateRange(ls);
}
鉴于所示的构造函数,从某些int
创建实例非常简单:
var result_a = new Abc(10, 20, 30);
现在,我可能还想要一个可以在给定Abc
的情况下构建IEnumerable<int>
的构造函数:
public Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
所以我们的班级现在看起来像这样:
class Abc
{
readonly ImmutableList<int> elts;
public Abc(params int[] ls) => elts = ImmutableList.CreateRange(ls);
public Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
}
这确实有效:
var ls = new[] { 10, 20, 30 };
var result_b = new Abc(ls);
但是,此构造函数有点尴尬,因为乍一看,是这样的:
new Abc(item)
可能看起来像是用单个元素(Abc
)创建一个item
。但是,如果item
实际上是一个包含多个项的IEnumerable<int>
,则将调用上面的第二个构造函数。
如果您查看Microsoft ImmutableList
API,它们实际上具有称为ImmutableList.CreateRange
的静态方法,该方法类似于上面的第二个构造函数。很好,因为我们避免了上述视觉上的歧义。
好的,让我们开始为Abc
类草绘一个类似的构造函数的简单实现:
public static Abc CreateRange(IEnumerable<int> ls)
{
elts = ImmutableList.CreateRange(ls);
...
}
当然,我们在这里遇到问题,因为elts
字段是readonly
,并且无法通过此静态方法初始化:
那么,为我们的CreateRange
类实现Abc
的一种好方法是什么?
答案 0 :(得分:2)
设置elts
的唯一方法是为Abc调用一个构造函数。
readonly
修饰符保证设置变量的唯一方法是在初始化期间,readonly int i=0;
或构造函数中。
该错误是由于静态方法无法访问Abc
的实例引起的,尽管您仍然无法对其进行修改,因为它是readonly
。
尝试以下方法:
public static Abc CreateRange(IEnumerable<int> ls)
{
return new Abc(ls);
}
答案 1 :(得分:1)
我相信SLaks的建议是创建一个私有构造函数,并从静态方法中调用它:
private Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
public static Abc CreateRange(IEnumerable<int> ls) => new Abc(ls);
这样,假设您没有任何公共构造函数,创建Abc
实例的唯一方法(无反射)是使用静态方法。