Как реализовать свойство только для чтения


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

Я вижу два способа сделать это:

  1. class MyClass
    {
        public readonly object MyProperty = new object();
    }
    
  2. class MyClass
    {
        private readonly object my_property = new object();
        public object MyProperty { get { return my_property; } }
    }
    

со всеми этими ошибками FxCop говоря, что я не должен иметь открытые переменные-члены, это кажется, что второй-это правильный способ сделать это. Правильно?

есть ли разница между свойством get only и членом только для чтения в этом случае?

буду признателен за любые комментарии/советы/и т. д.

6 60

6 ответов:

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

Конвенции:
Вы следуете конвенции. В таких случаях, когда различия между двумя возможностями относительно незначительны лучше следовать конвенции. Один случай, когда он может вернуться, чтобы укусить вас на основе отражения кода. Он может принимать только свойства, а не поля, например редактор свойств/зрителя.

сериализация
Переход от поля к свойству, вероятно, сломает много сериализаторов. И АФАИК XmlSerializer сериализует только общедоступные свойства, а не общедоступные поля.

используя Autoproperty
Другой распространенный вариант-это использование автопроперти с частным сеттером. Хотя это короткое и свойство, оно не применяет readonlyness. Поэтому я предпочитаю другие.

поле Readonly является самодокументирующим
Однако есть одно преимущество поля:
Это дает понять с первого взгляда на публичный интерфейс, что он фактически неизменен (за исключением отражения). В то время как в случае свойства вы можете видеть только это вы не может этого изменить, так что вам придется обратиться к документация или реализация.

но, честно говоря, я использую первый довольно часто в коде приложения, так как я ленив. В библиотеках я обычно более тщателен и следую конвенции.

В C# 6.0 добавляет только для чтения свойства авто

public object MyProperty { get; }

второй способ является предпочтительным вариантом.

private readonly int MyVal = 5;

public int MyProp { get { return MyVal;}  }

Это гарантирует, что MyVal может быть назначен только при инициализации (он также может быть установлен в конструкторе).

Как вы уже отметили - таким образом, вы не подвергаете внутренний член, что позволяет вам изменить внутреннюю реализацию в будущем.

С введением C# 6 (в VS 2015), теперь вы можете иметь get-только автоматические свойства, в которых подразумевается резервное поле readonly (т. е. значения могут быть назначены в конструкторе, но не в другом месте):

public string Name { get; }

public Customer(string name)  // Constructor
{
    Name = name;
}

private void SomeFunction()
{
    Name = "Something Else";  // Compile-time error
}

и теперь вы можете также инициализировать свойства (С или без сеттера) рядный:

public string Name { get; } = "Boris";

возвращаясь к вопросу, это дает вам преимущества варианта 2 (public member-это свойство, а не поле) с краткостью опции 1.

к сожалению, это не дает гарантии неизменности на уровне публичного интерфейса (как в пункте @CodesInChaos о самодокументации), потому что для потребителя класса отсутствие сеттера неотличимо от наличия частного сеттера.

вы можете сделать это:

public int Property { get { ... } private set { ... } }

Я согласен, что второй путь предпочтительнее. Единственной реальной причиной этого предпочтения является общее предпочтение, что классы .NET не имеют общедоступных полей. Однако, если это поле только для чтения, я не вижу, как будут какие-либо реальные возражения, кроме отсутствия согласованности с другими свойствами. Реальная разница между полем readonly и свойством get-only заключается в том, что поле readonly обеспечивает гарантию того, что его значение не изменится в течение срока службы объекта и get-only собственность - нет.

второй способ является предпочтительным из-за инкапсуляции. Вы, конечно, можете сделать поле readonly общедоступным, но это противоречит идиомам C#, в которых доступ к данным осуществляется через свойства, а не поля.

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