C#getter和setter简写

如果我对这条线的内部运作的理解是正确的:

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标志function的属性。

 public class IsDirtyDecorator { 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 MyInt = new IsDirtyDecorator(); private IsDirtyDecorator MyString = new IsDirtyDecorator(); 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 _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 _Integer; static int Integer { get { return _Integer.Value; } set { _Integer.Value = value; } } static void Main(string[] args) { _Integer = new Dirty(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标志。 您可能会发现以旧式方式执行它并不复杂,但这取决于您要公开的属性数量以及需要相同function的类数量。

 public class IsDirtyDecorator { private T _myValue; private Action _changedAction; public IsDirtyDecorator(Action 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 _myInt = new IsDirtyDecorator(onValueChanged); private IsDirtyDecorator _myOtherInt = new IsDirtyDecorator(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类来执行这样的常见操作。 我还没有彻底使用它,但它可以在这种情况下使用。

代码可以在这里找到: http : //pastebin.com/RWTWNNCU

您可以按如下方式使用它:

 readonly Property _myInt = new Property(); 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 )之外,这显然不会起作用,因为委托将不匹配。 您可以随时调整代码以满足您的需求。