[英]C# getter and setter shorthand
如果我对这条线的内部运作的理解是正确的:
public int MyInt { get; set; }
然后在幕后做这个:
private int _MyInt { get; set; }
Public int MyInt {
get{return _MyInt;}
set{_MyInt = value;}
}
我真正需要的是:
private bool IsDirty { get; set; }
private int _MyInt { get; set; }
Public int MyInt {
get{return _MyInt;}
set{_MyInt = value; IsDirty = true;}
}
但我想写一些类似于:
private bool IsDirty { get; set; }
public int MyInt { get; set{this = value; IsDirty = true;} }
哪个不起作用。 事情是我需要做的一些对象,IsDirty上有几十个属性,我希望有一种方法可以使用auto getter / setter,但是当字段被修改时仍然设置IsDirty。
这是可能的还是我只需要让自己在我的班级中将代码量增加三倍?
你需要自己处理:
private bool IsDirty { get; set; }
private int _myInt; // Doesn't need to be a property
Public int MyInt {
get{return _myInt;}
set{_myInt = value; IsDirty = true;}
}
没有可用的语法,在仍然使用自动属性机制的同时将自定义逻辑添加到setter。 您需要使用自己的支持字段来编写此代码。
这是一个常见问题 - 例如,在实现INotifyPropertyChanged
。
创建一个IsDirty装饰器(设计模式)来包装一些需要isDirty标志功能的属性。
public class IsDirtyDecorator<T>
{
public bool IsDirty { get; private set; }
private T _myValue;
public T Value
{
get { return _myValue; }
set { _myValue = value; IsDirty = true; }
}
}
public class MyClass
{
private IsDirtyDecorator<int> MyInt = new IsDirtyDecorator<int>();
private IsDirtyDecorator<string> MyString = new IsDirtyDecorator<string>();
public MyClass()
{
MyInt.Value = 123;
MyString.Value = "Hello";
Console.WriteLine(MyInt.Value);
Console.WriteLine(MyInt.IsDirty);
Console.WriteLine(MyString.Value);
Console.WriteLine(MyString.IsDirty);
}
}
你可以简单或复杂。 这取决于你想投入多少工作。 您可以使用面向方面编程通过IL weaver将方面添加到IL代码中,例如使用PostSharp 。 或者,您可以创建一个处理属性状态的简单类。 这很简单,如果你有很多属性来处理这种方式,前一种方法只会得到回报。
using System;
class Dirty<T>
{
T _Value;
bool _IsDirty;
public T Value
{
get { return _Value; }
set
{
_IsDirty = true;
_Value = value;
}
}
public bool IsDirty
{
get { return _IsDirty; }
}
public Dirty(T initValue)
{
_Value = initValue;
}
}
class Program
{
static Dirty<int> _Integer;
static int Integer
{
get { return _Integer.Value; }
set { _Integer.Value = value; }
}
static void Main(string[] args)
{
_Integer = new Dirty<int>(10);
Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer);
Integer = 15;
Console.WriteLine("Dirty: {0}, value: {1}", _Integer.IsDirty, Integer);
}
}
另一种可能性是使用在运行时生成的代理类,它会为您添加方面。 使用.NET 4,有一个类已经为您处理这方面。 它被称为ExpandObject ,它会在属性发生变化时通过事件通知您。 好处是ExpandoObject允许您在运行时定义任何数量的属性,并获得有关属性的每个更改的通知。 使用此类型,使用WPF进行数据绑定非常容易。
dynamic _DynInteger = new ExpandoObject();
_DynInteger.Integer = 10;
((INotifyPropertyChanged)_DynInteger).PropertyChanged += (o, e) =>
{
Console.WriteLine("Property {0} changed", e.PropertyName);
};
Console.WriteLine("value: {0}", _DynInteger.Integer );
_DynInteger.Integer = 20;
Console.WriteLine("value: {0}", _DynInteger.Integer);
你的,Alois Kraus
我要补充Simon Hughes的回答。 我提出了相同的建议,但添加了一种方法来允许装饰器类自动更新全局IsDirty标志。 您可能会发现以旧式方式执行此操作并不复杂,但这取决于您要公开的属性数量以及需要相同功能的类别数量。
public class IsDirtyDecorator<T>
{
private T _myValue;
private Action<bool> _changedAction;
public IsDirtyDecorator<T>(Action<bool> changedAction = null)
{
_changedAction = changedAction;
}
public bool IsDirty { get; private set; }
public T Value
{
get { return _myValue; }
set
{
_myValue = value;
IsDirty = true;
if(_changedAction != null)
_changedAction(IsDirty);
}
}
}
现在,您可以让您的装饰器类自动更新另一个类中的其他一些IsDirty属性:
class MyObject
{
private IsDirtyDecorator<int> _myInt = new IsDirtyDecorator<int>(onValueChanged);
private IsDirtyDecorator<int> _myOtherInt = new IsDirtyDecorator<int>(onValueChanged);
public bool IsDirty { get; private set; }
public int MyInt
{
get { return _myInt.Value; }
set { _myInt.Value = value; }
}
public int MyOtherInt
{
get { return _myOtherInt.Value; }
set { _myOtherInt.Value = value; }
}
private void onValueChanged(bool dirty)
{
IsDirty = true;
}
}
我已经创建了一个自定义Property<T>
类来执行这样的常见操作。 虽然我还没有彻底使用它,但它可以在这种情况下使用。
代码可以在这里找到: http : //pastebin.com/RWTWNNCU
您可以按如下方式使用它:
readonly Property<int> _myInt = new Property<int>();
public int MyInt
{
get { return _myInt.GetValue(); }
set { _myInt.SetValue( value, SetterCallbackOption.OnNewValue, SetDirty ); }
}
private void SetDirty( int oldValue, int newValue )
{
IsDirty = true;
}
由于SetterCallbackOption
参数传递新值,Property类仅处理调用传递的委托。 这是默认设置,因此可以删除它。
更新:
当你需要支持多种类型(除了int
)之外,这显然不会起作用,因为委托将不匹配。 您可以随时调整代码以满足您的需求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.