如果需要自定义getter/setter,可以省略字段创建吗?
本文关键字:字段 创建 自定义 getter setter 如果 | 更新日期: 2023-09-27 18:16:13
我可以写出这样漂亮直接的代码:
public int Delta { get; private set; }
现在我想添加一个调用OnPropertyChanged("Delta");
这是我知道的唯一方法:
public int Delta { get { return _delta; } private set
{
_delta = value; OnPropertyChanged("Delta"); }
}
private int _delta;
额外代码太多了!为什么我要在这个例子中引入场?你能把这段代码写短一点吗?我想有这样的东西,但它不工作:
public int Delta { get; private set { OnPropertyChanged("Delta"); } }
不能使用auto-properties。自动属性是指字段上的属性的简写语法。他们实际上没有其他能力。任何自定义代码执行都需要一个完整的属性。
我为此创建了以下代码片段(示例):
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name != value) {
_Name = value;
OnPropertyChanged("Name");
}
}
}
片段:
<?xml version="1.0"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Title>propn (Creates a notifying property)</Title>
<Shortcut>propn</Shortcut>
<Description>This snippet helps implementing INotifyPropertyChanged by creating a property with backing store. The settter calls OnPropertyChanged if the value changes. Use the "notify" code snippet in order to implement INotifyPropertyChanged.</Description>
<Author>Olivier Jacot-Descombes</Author>
</Header>
<Snippet>
<Declarations>
<Literal Editable="false">
<ID>classname</ID>
<ToolTip>Name of class</ToolTip>
<Default>ClassNamePlaceholder</Default>
<Function>ClassName()</Function>
</Literal>
<Literal Editable="true">
<ID>NameOfProperty</ID>
<ToolTip>
</ToolTip>
<Default>MyProp</Default>
<Function>
</Function>
</Literal>
<Literal Editable="true">
<ID>Type</ID>
<ToolTip>
</ToolTip>
<Default>int</Default>
<Function>
</Function>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[private $Type$ _$NameOfProperty$;
public $Type$ $NameOfProperty$
{
get { return _$NameOfProperty$; }
set
{
if (_$NameOfProperty$ != value) {
_$NameOfProperty$ = value;
OnPropertyChanged("$NameOfProperty$");
}
}
}
]]></Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
将此代码复制到文本文件中。给它一个扩展。"你可以使用代码片段管理器(工具菜单)将其导入到Visual Studio中。
下面是另一个创建事件处理程序的代码片段(示例):
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
//TODO: Inherit interface System.ComponentModel.INotifyPropertyChanged.
//TODO: Create properties with the propn code snippet.
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
片段:
<?xml version="1.0"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Title>notify (Implements INotifyPropertyChanged)</Title>
<Shortcut>notify</Shortcut>
<Description>This snippet the inserts the INotifyPropertyChanged implementation into a class</Description>
<Author>Olivier Jacot-Descombes</Author>
</Header>
<Snippet>
<Declarations>
<Literal Editable="false">
<ID>classname</ID>
<ToolTip>Name of class</ToolTip>
<Default>ClassNamePlaceholder</Default>
<Function>ClassName()</Function>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
//TODO: Inherit interface System.ComponentModel.INotifyPropertyChanged.
//TODO: Create properties with the propn code snippet.
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion]]></Code>
</Snippet>
</CodeSnippet>
<CodeSnippet Format="1.0.0">
<Header>
<Title>
</Title>
<Shortcut>
</Shortcut>
<Description>
</Description>
<Author>
</Author>
</Header>
<Snippet>
<Code Language="csharp"><![CDATA[]]></Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
考虑它不是那么漂亮!参考Seeman的博客文章:Code Smell: Automatic Property
。NET属性是在底层生成的type get_PropertyName()
和set_PropertyName(type value)
方法的语法糖,get_
返回底层字段值,set_
明显更新底层字段值。所以有两种选择:要么你通过指定属性getter/setter来提供自己的方法体,要么让框架为你生成支持字段,这样就没有第三种情况了。
如果你想简化你的PropertyChanged
例程,你可以看看notifypropertyweaver
之后你的代码将看起来像:
[NotifyProperty(PerformEqualityCheck = false)]
public int Delta { get; set; }
不幸的是,情况就是这样。如果你使用的是c# 4.0,你可以使用动态对象,并且以牺牲类型安全为代价使用更少的代码。
简而言之
public override bool TrySetMember(SetMemberBinder binder, object value)
{
//set the actual property and do
OnPropertyChanged(binder.Name);
}
TrySetMember可能有更多的代码要写,但是你可以在同一个类的多个属性中共享它。
如果你不介意任何第三方框架,你可以使用AOP框架,如PostSharp,它为你做锅炉板代码。
不幸的是没有办法做到这一点。这种类型的构造在面向方面的编程中是可能的,但在c#编译器中迄今为止还没有任何生产版本。
没有通用的更好的方法来做到这一点,但你可以尝试使用像Resharpers snippets of VS snippets这样的模板引擎来更快地编写这些。
在某些情况下,当元数据可用时,您还可以使用代码生成来简化此操作。
自动属性是一个"全有或全无"的交易。
它们所做的只是创建一个后备字段,在get访问器中返回其值,并在set访问器中设置其值。如果您想做任何额外的事情,您必须定义支持字段并手动实现get和set。没有别的办法。
你可能想知道为什么你甚至需要一个自动属性,如果它没有任何逻辑?为什么不直接定义一个公共字段呢?但是,假设您定义了一个auto属性,并且其他程序集使用您的程序集。现在,如果您决定更改手动实现的属性以添加一些逻辑,则使用您的程序集的程序集不必重新编译。如果你从一个字段切换到一个属性,它们将中断,必须重新编译。
这里是我的交互式。net教程部分的直接链接,在那里我详细讨论了属性:http://motti.me/s2a
如果你感兴趣,这里是整个教程的链接:http://motti.me/c0
我希望这有助于!