C# 具有私有setter的属性与仅获取属性
C#6.0引入了定义仅获取属性的功能:C# 具有私有setter的属性与仅获取属性,c#,wpf,mvvm,c#-6.0,C#,Wpf,Mvvm,C# 6.0,C#6.0引入了定义仅获取属性的功能: public ICommand AddCommand { get; } 现在,当定义另一个类似以下内容的属性时,ReSharper建议将Auto属性设置为“仅获取”: 公共get-only属性(例如第一个AddCommand)、私有get-only属性(例如屏幕截图属性)和公共私有setter属性(例如第二个AddCommand)之间有什么区别 我的WPF应用程序似乎并不关心它的公共属性(UICommand)是否包含私有setter,但肯定有区别吗?在绑
public ICommand AddCommand { get; }
现在,当定义另一个类似以下内容的属性时,ReSharper建议将Auto属性设置为“仅获取”:
公共get-only属性(例如第一个AddCommand
)、私有get-only属性(例如屏幕截图
属性)和公共私有setter属性(例如第二个AddCommand
)之间有什么区别
我的WPF应用程序似乎并不关心它的公共属性(UICommand)是否包含私有setter,但肯定有区别吗?在绑定命令的特定情况下,这并不重要 在其他情况下,例如,拥有一个通过构造函数注入服务的类,并且您想要公开它(无论出于何种原因),使用只读属性非常重要 例如:
public class MainViewModel
{
public INavigationService NavigationService { get; }
public MainViewModel(INavigationService navigationService)
{
if(navigationService == null)
throw new ArgumentNullException(navigationServie);
NavigationService = navigationService;
}
}
使用此选项时,您可以保证此类不变量,并确保NavigationService
永远不会为null
,因此在使用它之前不需要对NavigationService
执行null检查。一旦它离开构造函数,它就永远不能被更改(好吧,除非通过反射)
在另一边,如果你有
public class MainViewModel
{
public INavigationService NavigationService { get; private set; }
public MainViewModel(INavigationService navigationService)
{
if(navigationService == null)
throw new ArgumentNullException(navigationServie);
NavigationService = navigationService;
}
}
然后,就有可能(错误地或由没有经验的开发人员)编写代码,而该代码不执行NavigationService=null
,如果您没有null检查并访问它,您将得到NullReferenceException
,如果不处理,您的应用程序将崩溃
回到您的示例:如果是ICommand
。。。通常不访问ViewModel中的命令,只分配它(通常在构造函数中,或者当视图模型的内容发生更改时,如子视图模型发生更改,并且希望将其命令分配给父视图模型命令属性时)
如果是列表:
如果您从未在代码中执行Screenshots=newlist()
或Screenshots=displayshreenshots()
,并且只在构造函数中对其进行初始化,那么出于同样的原因,最好将其设置为只读:这样您就可以保证Screenshots
永远不为空,并且不必编写诸如
if(Screenshots != null)
{
Screenshots.Add(new Screenshot(...));
}
或
这有一个巨大的优势,即您需要更少的代码,您的代码更具可读性和可维护性,因为您不能“忘记”空检查并冒出现NullReferenceException
的风险
希望一切都会好起来 简短回答:
public ICommand AddCommand { get; }
将由一个只读
字段支持,并且在构造函数执行之后,任何C#代码都无法对其进行更改
此外,编译器将生成代码来直接分配支持文件,因为没有属性访问器
另一方面:
public ICommand AddCommand { get; private set; }
将由一个非只读字段支持,并且可以在任何时候由访问私人成员的任何代码分配
在这种情况下,编译器将生成正常的属性设置代码
对外界来说,一个私密的塞特人似乎并不存在。所以,它就像它不存在一样。编译器为您做了功课后,您的属性会变成什么样子:
1<代码>公共ICommand AddCommand{get;}:
private readonly ICommand <AddCommand>k__BackingField;
public ICommand AddCommand {
get { return this.<AddCommand>k__BackingField; }
}
private List<Screenshot> <Screenshots>k__BackingField;
private List<Screenshot> Screenshots {
get { return this.<Screenshots>k__BackingField; }
set { this.<Screenshots>k__BackingField = value; }
}
private ICommand <AddCommand>k__BackingField;
public ICommand AddCommand {
get { return this.<AddCommand>k__BackingField; }
private set { this.<AddCommand>k__BackingField = value; }
}
简言之,只能在构造函数中(因为字段是只读的)或通过以下新语法分配公共get-only属性:
public ICommand AddCommand { get; } = new MyCommand();
但对于任何其他只读字段,此代码无论如何都会放入构造函数中,因此没有太大区别:
public MyClass1()
{
this.<AddCommand>k__BackingField = new MyCommand();
}
公共MyClass1()
{
this.k_ubackingfield=新的MyCommand();
}
Get-only属性类似于readonly
字段,它们可以在对象构造/初始化中设置,但不能在以后设置。私有setter不能保证其他方法在构造后不能修改其值。第一个属性(AddCommand
)中的“新”是什么?@Amit:set访问器丢失。@RonBeyer因此,对于WPF MVVM,当命令在ViewModel的构造函数中创建时,如果您想说ICommand
在设置后不会更改,那么最好使用get-only属性?这是一种方法。如果它的好坏是一个意见问题,但如果它没有改变,并且您正在使用C#6,那么如果您试图在意外情况下重新分配它,它可以使事情更容易理解,并给出编译错误。
private List<Screenshot> <Screenshots>k__BackingField;
private List<Screenshot> Screenshots {
get { return this.<Screenshots>k__BackingField; }
set { this.<Screenshots>k__BackingField = value; }
}
private ICommand <AddCommand>k__BackingField;
public ICommand AddCommand {
get { return this.<AddCommand>k__BackingField; }
private set { this.<AddCommand>k__BackingField = value; }
}
public ICommand AddCommand { get; } = new MyCommand();
public MyClass1()
{
this.<AddCommand>k__BackingField = new MyCommand();
}