私有setter与get-only-property的属性

C#6.0引入了定义只获取属性的function:

public ICommand AddCommand { get; } 

现在,当定义如下的另一个属性时,ReSharper建议Auto-property可以变为get-only

 private List Screenshots { get; set; } 

此外,ReSharper在定义私人吸气剂时并未说出一句话:

 public ICommand AddCommand { get; private set; } 

公共get-only属性(例如第一个AddCommand ),private get-only属性(例如Screenshots属性)和public private setter属性(例如第二个AddCommand )之间的AddCommand什么?

我的WPF应用程序似乎并不关心它的公共属性(UICommand)是否包含私有的setter或者根本没有setter,但肯定必须有区别?

在绑定命令的这种特定情况下,它并不重要。

在其他情况下,即有一个类通过构造函数注入服务并且您想要公开它(无论出于何种原因),使用只读属性很重要。

例如:

 public class MainViewModel { public INavigationService NavigationService { get; } public MainViewModel(INavigationService navigationService) { if(navigationService == null) throw new ArgumentNullException(navigationServie); NavigationService = navigationService; } } 

使用它时,您可以保证此类不变量,并确保NavigationService永远不会为null ,因此在使用之前不需要对NavigationService进行空检查。 一旦它离开构造函数,它就不会被改变(好吧,除非通过reflection)。

另一方面,如果你有

 public class MainViewModel { public INavigationService NavigationService { get; private set; } public MainViewModel(INavigationService navigationService) { if(navigationService == null) throw new ArgumentNullException(navigationServie); NavigationService = navigationService; } } 

然后可以编写代码(错误地或由没有经验的开发人员)执行NavigationService = null然后如果你没有空检查并访问它,你将得到一个NullReferenceException ,如果没有处理你的应用程序崩溃。

回到你的例子:在ICommand情况下…你通常不访问ViewModel中的命令,只分配它(通常在构造函数中或当你的视图模型的内容发生变化时,就像子视图模型改变了你想要分配它是父视图模型命令属性的命令。

如果是清单:

如果您从未在代码中执行Screenshots = new List()Screenshots = DisplayScreenshots()并且仅在构造函数中初始化它,那么确实更好的方法是将其读取为同样的原因:然后您可以保证Screenshots永远不会为null,您不必编写诸如此类的代码

 if(Screenshots != null) { Screenshots.Add(new Screenshot(...)); } 

要么

 if(Screenshot == null) { Screenshots = new List(); } Screenshots.Add(new Screenshot(...)); 

再次,而不是总是使用

 Screenshots.Add(new Screenshot(...)); 

这有一个巨大的优势,你需要更少的代码,你的代码更易读和更易于维护,因为你不能“忘记”空检查并冒险NullReferenceException

希望清理它。

简短回答:

 public ICommand AddCommand { get; } 

将由readonly字段支持,并且除了构造函数的执行之外,没有C#代码能够更改它。

此外,编译器将生成代码以直接分配后备字段,因为没有属性访问器。

另一方面:

 public ICommand AddCommand { get; private set; } 

将由非readonly字段支持,并且可以随时通过任何可访问私有成员的代码进行分配。

在这种情况下,编译器将生成正常的属性设置代码。

对外界来说,私人制定者就好像它不存在一样。 所以,它就像它真的不存在一样。

以下是编译器为您完成作业后属性的变化:

1. public ICommand AddCommand { get; } public ICommand AddCommand { get; }

 private readonly ICommand k__BackingField; public ICommand AddCommand { get { return this.k__BackingField; } } 

2. private List Screenshots { get; set; } private List Screenshots { get; set; } private List Screenshots { get; set; }

 private List k__BackingField; private List Screenshots { get { return this.k__BackingField; } set { this.k__BackingField = value; } } 

3. public ICommand AddCommand { get; private set; } public ICommand AddCommand { get; private set; } public ICommand AddCommand { get; private set; }

 private ICommand k__BackingField; public ICommand AddCommand { get { return this.k__BackingField; } private set { this.k__BackingField = value; } } 

简而言之,只能在构造函数中指定public get-only属性 (因为该字段是只读的)或通过以下新语法:

 public ICommand AddCommand { get; } = new MyCommand(); 

但对于任何其他只读字段,此代码无论如何都被置于构造函数中,因此没有太大区别:

 public MyClass1() { this.k__BackingField = new MyCommand(); }