我正在尝试创建一个包含值的类,每当值发生变化时都会引发一个事件,并且会隐式转换为它所持有的类型。
我的目标是我应该能够创建一个类的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定义了两次。这是一个有点hackish的解决方法,我正在考虑以另一种方式定义隐式转换(正如你们许多人所建议的那样):
public static implicit operator Observable<T>(T value)
{
var result = new Observable<T>();
result.SetValueSilently(value);
return result;
}
并使用它来调用属性的setter:
public Observable<string> Property
{
get { return _property; }
set { _property.Value = value.Value; }
}
答案 0 :(得分:4)
您可以重载implicit
运算符。
public static operator implicit string(YourObject object)
并走另一条路
public static operator implicit YourObject(string s)
请注意,这非常很危险。它可以导致班上的消费者做一些你从未想过的事情;以及一些没有意义的行为。
答案 1 :(得分:4)
如果查看Overloadable Operators in C#,您会看到:
分配运算符不能重载,但是+ =,例如,使用+来计算,可以重载。
但是,您可以设置implicit operator Observable<T>(T value)
,这样您就可以隐式地从T
转换为Observable<T>
。
话虽如此,我不会推荐这个。我会明确地赋值,因为这需要在每次调用时创建一个 new Observable<T>
,这将导致事件处理程序出现问题,因为每个赋值都会创建一个新的对象实例。
答案 2 :(得分:3)
在这些行中添加另一个隐式转换:
public static implicit operator Observable<T>(T value)
{
return new Observable<T>{Value = value};
}