Как реализовать свойство только для чтения
мне нужно реализовать только для чтения собственность в моем вкусе. Кроме того, значение этого свойства будет в конструкторе и он не будет изменен (я пишу класс, который выставляет свои команды направляются UI для WPF, но это не важно).
Я вижу два способа сделать это:
class MyClass { public readonly object MyProperty = new object(); }
class MyClass { private readonly object my_property = new object(); public object MyProperty { get { return my_property; } } }
со всеми этими ошибками FxCop говоря, что я не должен иметь открытые переменные-члены, это кажется, что второй-это правильный способ сделать это. Правильно?
есть ли разница между свойством get only и членом только для чтения в этом случае?
буду признателен за любые комментарии/советы/и т. д.
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 о самодокументации), потому что для потребителя класса отсутствие сеттера неотличимо от наличия частного сеттера.
Я согласен, что второй путь предпочтительнее. Единственной реальной причиной этого предпочтения является общее предпочтение, что классы .NET не имеют общедоступных полей. Однако, если это поле только для чтения, я не вижу, как будут какие-либо реальные возражения, кроме отсутствия согласованности с другими свойствами. Реальная разница между полем readonly и свойством get-only заключается в том, что поле readonly обеспечивает гарантию того, что его значение не изменится в течение срока службы объекта и get-only собственность - нет.
второй способ является предпочтительным из-за инкапсуляции. Вы, конечно, можете сделать поле readonly общедоступным, но это противоречит идиомам C#, в которых доступ к данным осуществляется через свойства, а не поля.
причина этого заключается в том, что свойство определяет открытый интерфейс, и если резервная реализация этого свойства изменяется, вы не нарушаете остальную часть кода, потому что реализация скрыта за интерфейсом.