也许是一个愚蠢的问题,但是......
在我的代码中,我在几个地方使用以下构造。
void MyFunction()
{
DoSomething(myClass.myProperty)
myClass.PropertyChanged += (s,e ) => {
if (e.PropertyName == "myProperty") {
DoSomething(myClass.myProperty);
}
}
}
所以我想在最初做一些事情,并且在将来属性发生变化时也会这样做。
现在的问题是,MyFunction()在程序执行期间被多次调用。我将分配给PropertyChanged的代表是否会通过此方法添加evertime? (每次迭代消耗更多内存并减慢程序速度)或者编译器/运行时足够聪明,我应该只在第一次添加...?如果是这样,这是如何工作的?
答案 0 :(得分:4)
编译器无法知道你的意图......它会在每次调用MyFunction()时忠实地附加事件处理程序。
以这种方式看待它们 - 它们的编译器无法知道函数中的引用变量(例如myclass
)是指您之前附加处理程序的对象的相同实例。也不知道你没有在调用之间的其他地方分离处理程序。它无法做出这样的假设。
然而,您可以重构代码,以便处理程序只附加一次。由于其他消费者可能订阅PropertyChanged事件,因此您需要保留一些独立状态以了解您是否已订阅。例如:
if( !haveSubscribedToPropertyChanged ) {
myClass.PropertyChanged += (s,e ) => {
if (e.PropertyName == "myProperty") {
DoSomething(myClass.myProperty);
}
}
haveSubscribedToPropertyChanged = true;
}
答案 1 :(得分:3)
许多其他答案建议您应检查PropertyChanged
事件是否为null
,以防止添加多个侦听器。该解决方案的一个问题是PropertyChanged
可能是非null
,如果代码的其他部分侦听同一事件但是另一个属性,如此。
void AnotherFunction()
{
myClass.PropertyChanged += (s,e) => {
if (e.PropertyName == "anotherProperty") {
DoSomethingElse(myClass.anotherProperty);
}
}
}
在我看来,更好的解决方案是维护一个最初为false的布尔标志,并且仅在调用MyFunction
时设置为true。然后,检查此标志是否需要添加事件处理程序。