7

我正在尝试创建一个包含一个值的类,每当值更改时都会引发一个事件,并将隐式转换为它所持有的类型。

我的目标是我应该能够创建一个类的 Observable 属性,并让另一个类(包括 WPF 控件)能够像普通字符串一样读取和写入它。其他类可以维护对它的引用作为 Observable,甚至将其公开为自己的属性,而无需创建新事件。

这是我到目前为止所拥有的:

using System;
using System.ComponentModel;

namespace SATS.Utilities
{
    public class Observable<T>
    {
        private T mValue;

        public event EventHandler ValueChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyValueChanged()
        {
            if (ValueChanged != null)
            {
                ValueChanged(this, new EventArgs());
            }
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Value"));
            }
        }

        public T Value
        {
            get
            {
                return mValue;
            }
            set
            {
                SetValueSilently(value);
                NotifyValueChanged();
            }
        }

        public void SetValueSilently(T value)
        {
            mValue = value;
        }

        public static implicit operator T(Observable<T> observable)
        {
            return observable.Value;
        }

        public static T operator =(Observable<T> observable, T value) // Doesn't compile!
        {
            observable.Value = value;
            return value;
        }
    }
}

问题是“=”运算符抱怨它不能重载。我想这是有道理的,因为它可能导致各种奇怪的行为。还有另一种方法可以实现我的目标吗?

编辑:这是我决定如何实施的。让我知道是否有更好的建议:)

我意识到这种情况应该由持有 Observable 的属性来处理。这是我想做的一个例子:

public class A
{
    private readonly Observable<string> _property;

    public Observable<string> Property
    {
        get { return _property; }
    }

    public string Property
    {
        set { _property.Value = value; }
    }
}

当然,这不会编译,因为 Property 被定义了两次。这是我正在考虑以另一种方式定义隐式转换的有点骇人听闻的解决方法(正如你们中的许多人所建议的那样):

public static implicit operator Observable<T>(T value)
{
    var result = new Observable<T>();
    result.SetValueSilently(value);
    return result;
}

并使用它来调用属性的设置器:

public Observable<string> Property
{
    get { return _property; }
    set { _property.Value = value.Value; }
}
4

3 回答 3

4

如果您查看C# 中的可重载运算符,您会看到:

赋值运算符不能重载,但 +=,例如,使用 + 计算,可以重载。

但是,您可以制作一个implicit operator Observable<T>(T value),这将允许您从 隐式转换TObservable<T>

话虽如此,我不会推荐这个。我会明确分配,因为这需要在每次调用它时创建一个新的,这将导致您的事件处理程序出现问题,因为每个分配都会创建一个新的对象实例。 Observable<T>

于 2012-12-21T19:36:45.703 回答
4

您可以重载implicit运算符。

public static operator implicit string(YourObject object)

走另一条路

public static operator implicit YourObject(string s)

但是请注意,这是非常危险的。它可以导致类的消费者做一些你从未想过的事情;以及一些没有意义的行为。

于 2012-12-21T19:31:24.263 回答
3

添加另一个隐式转换,如下所示:

public static implicit operator Observable<T>(T value)
{
    return new Observable<T>{Value = value};
}
于 2012-12-21T19:33:43.833 回答