Инициализация частные средства доступа к одному и тому же свойству?

#c# #c#-9.0

#c# #c #-9.0

Вопрос:

Можно ли использовать общедоступный метод инициализации и частный сеттер для одного и того же свойства?

В настоящее время я получаю ошибку CS1007 «Средство доступа к свойству уже определено».

 public record Stuff
{
    public int MyProperty { get; init; private set; } // Error

    public void SetMyProperty(int value) => MyProperty = value;
}

var stuff = new Stuff
{
    MyProperty = 3, // Using the init accessor
};

stuff.SetMyProperty(4); // Using the private setter (indirectly)
  

Моим лучшим предположением было бы использовать закрытую переменную-член, свойство для этой переменной с get init помощью средств доступа и (не реализуемых автоматически) и функции-члена setter . Можно ли это сделать проще?

Комментарии:

1. Какой в этом смысл? Вы пытаетесь дважды указать установщик. init это тоже сеттер

2. Это невозможно, нет. Средство init доступа использует тот же set_MyProperty метод set set, что и средство доступа: оно просто украшено a modreq .

3. Вся идея init состоит в том, чтобы сделать свойство неизменяемым. Наличие установщика противоречит этой цели

4. Цель состоит в том, чтобы иметь «в основном неизменяемые» объекты, где правило thumb является неизменяемым, но есть несколько четко определенных исключений. Мы можем использовать with , но это не делает возможной какую-либо логику (например, проверки согласованности).

5. Я думаю, лучшим решением, которое я мог бы предложить для этого, было бы использовать частный сеттер и установить начальное значение через конструктор.

Ответ №1:

Аналогично указанию конструктора для инициализации вашего значения, вы можете использовать частное резервное поле, чтобы вы все еще могли воспользоваться преимуществами логики инициализации и разрешить инициализацию без определенного конструктора

 public record Stuff
{
    private int _myProperty;

    public int MyProperty { get => _myProperty; init => _myProperty = value; }

    public void SetMyProperty(int value) => _myProperty = value;
}

var stuff = new Stuff
{
    MyProperty = 3 // Using the init accessor
};

stuff.SetMyProperty(4); // Using the private setter (indirectly)
  

Ответ №2:

Нет, вы не можете. Ключевое слово init было добавлено в попытке сделать неизменяемые свойства объектов.

Итак, если у вас есть запись:

 public record Stuff
{
    public int MyProperty { get; init; } // This can not be changed after initialization
}
  

MyProperty может быть установлен только во время инициализации вашей записи.

Если вы хотите, чтобы ваше свойство было изменяемым, тогда вы используете средство set доступа вместо init .

 public record Stuff
{
    public int MyProperty { get; set; } // This can
}
  

Комментарии:

1. Спасибо, Хасан, я имел в виду set

Ответ №3:

В качестве ответа @Jerry’s вы не можете использовать оба средства установки. Это связано с изменчивостью записи / объекта.

Если вы также хотите иметь private set ers и некоторую логику инициализации, я использую конструкторы:

 public record Stuff
{
    public Stuff(int myProperty)
    {
        MyProperty = myProperty;
    }

    public int MyProperty { get; private set; }

    public void SetMyProperty(int value) => MyProperty = value;
}

var stuff = new Stuff(3);
stuff.SetMyProperty(4);
  

Все дело в требованиях к домену.

  • Stuff.MyProperty Нужно ли публично изменять?
  • Если это так, каким будет значение этого свойства по умолчанию при инициализации экземпляра Stuff? Ожидает ли домен значение по умолчанию?

и т.д..