class 的构造函数,具有不可变存储的只读字段
Constructor for class with readonly field of immutable storage
假设我们有以下简单的class。请注意,唯一的字段是 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);
现在,我可能还想要一个可以在给定 IEnumerable<int>
:
的情况下构建 Abc
的构造函数
public Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
所以我们的 class 现在看起来像这样:
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)
可能看起来像是在用单个元素 (item
) 创建 Abc
。但是,如果 item
实际上是一个包含多个项目的 IEnumerable<int>
,则将调用上面的第二个构造函数。
如果你看一下 Microsoft ImmutableList
API,他们实际上有一个名为 ImmutableList.CreateRange
的静态方法,类似于上面的第二个构造函数。这很好,因为我们避免了上述视觉歧义。
好的,让我们开始为我们的 Abc
class:
草拟一个类似构造函数的简单实现
public static Abc CreateRange(IEnumerable<int> ls)
{
elts = ImmutableList.CreateRange(ls);
...
}
当然,我们运行在这里遇到了一个问题,因为elts
字段是readonly
并且不能通过这个静态方法初始化:
那么,为我们的 Abc
class 实施 CreateRange
的好方法是什么?
设置 elts
的唯一方法是调用 Abc 的构造函数。
readonly
修饰符保证设置变量的唯一方法是在初始化期间,readonly int i=0;
或在构造函数中。
该错误是由于静态方法无法访问 Abc
的实例引起的,尽管您仍然无法修改它,因为它是 readonly
.
试试这个:
public static Abc CreateRange(IEnumerable<int> ls)
{
return new Abc(ls);
}
我相信 SLaks 的建议是创建一个私有构造函数并从静态方法中调用它:
private Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
public static Abc CreateRange(IEnumerable<int> ls) => new Abc(ls);
创建 Abc
实例的唯一方法(无需反射)是使用静态方法,假设您没有任何 public 构造函数。
假设我们有以下简单的class。请注意,唯一的字段是 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);
现在,我可能还想要一个可以在给定 IEnumerable<int>
:
Abc
的构造函数
public Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
所以我们的 class 现在看起来像这样:
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)
可能看起来像是在用单个元素 (item
) 创建 Abc
。但是,如果 item
实际上是一个包含多个项目的 IEnumerable<int>
,则将调用上面的第二个构造函数。
如果你看一下 Microsoft ImmutableList
API,他们实际上有一个名为 ImmutableList.CreateRange
的静态方法,类似于上面的第二个构造函数。这很好,因为我们避免了上述视觉歧义。
好的,让我们开始为我们的 Abc
class:
public static Abc CreateRange(IEnumerable<int> ls)
{
elts = ImmutableList.CreateRange(ls);
...
}
当然,我们运行在这里遇到了一个问题,因为elts
字段是readonly
并且不能通过这个静态方法初始化:
那么,为我们的 Abc
class 实施 CreateRange
的好方法是什么?
设置 elts
的唯一方法是调用 Abc 的构造函数。
readonly
修饰符保证设置变量的唯一方法是在初始化期间,readonly int i=0;
或在构造函数中。
该错误是由于静态方法无法访问 Abc
的实例引起的,尽管您仍然无法修改它,因为它是 readonly
.
试试这个:
public static Abc CreateRange(IEnumerable<int> ls)
{
return new Abc(ls);
}
我相信 SLaks 的建议是创建一个私有构造函数并从静态方法中调用它:
private Abc(IEnumerable<int> ls) => elts = ImmutableList.CreateRange(ls);
public static Abc CreateRange(IEnumerable<int> ls) => new Abc(ls);
创建 Abc
实例的唯一方法(无需反射)是使用静态方法,假设您没有任何 public 构造函数。