Допустим, у нас есть следующий простой класс.Обратите внимание, что единственное поле - readonly
и предназначено для ImmutableList<int>
:
class Abc
{
readonly ImmutableList<int> elts;
public Abc(params int[] ls) => elts = ImmutableList.CreateRange(ls);
}
. Учитывая показанный конструктор, довольно легко создать экземпляр из некоторых int
s:
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);
...
}
OfКонечно, мы столкнулись с проблемой здесь, потому что поле elts
равно readonly
и не может быть инициализировано с помощью этого статического метода:
![enter image description here](https://i.stack.imgur.com/QFQkb.png)
Итак,Каков хороший подход для реализации CreateRange
для нашего Abc
класса?