C#getter和setter简写

时间:2011-02-15 21:36:51

标签: c# getter-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上有几十个属性,我希望有一种方法可以使用自动getter / setter,但是当字段被修改时仍然设置IsDirty。

这是可能的吗?或者我只是要让自己辞去我课程中的代码量三倍?

5 个答案:

答案 0 :(得分:24)

你需要自己处理:

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时。

答案 1 :(得分:11)

创建一个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);
    }
}

答案 2 :(得分:2)

你可以简单或复杂。这取决于你想投入多少工作。您可以使用面向方面的编程通过IL编织器将方面添加到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

答案 3 :(得分:2)

我要补充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;
    }

}

答案 4 :(得分:1)

我创建了一个自定义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除外)时,这显然不起作用,因为委托将不匹配。您可以随时调整代码以满足您的需求。