私有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
private List
private List
:
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(); }