gpt4 book ai didi

c# - 为什么在 C# 中禁止为发件人发送事件?

转载 作者:太空狗 更新时间:2023-10-30 00:06:24 25 4
gpt4 key购买 nike

引用自: http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx

“只能从声明事件的类中调用事件。”

我很纳闷为什么会有这样的限制。如果没有这个限制,我将能够编写一个类(一个类),它可以很好地管理发送给定类别的事件——比如 INotifyPropertyChanged

由于此限制,我必须重新复制并粘贴相同(相同!)的代码。我知道 C# 的设计者不太看重代码重用 (*),但是哎呀……复制和粘贴。这有多高效?

    public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}

在每一节课上改变一些东西,直到你生命的尽头。可怕!

所以,当我将我的额外发送类(我太容易上当受骗)恢复为旧的“好”复制和粘贴方式时,你能看到吗

为发送者发送事件的能力会发生什么可怕的事情?

如果您知道如何避免此限制的任何技巧 - 请不要犹豫回答!

(*) 有了多重继承,我可以用更清晰的方式写一次通用发送器,但 C# 没有多重继承

编辑

迄今为止最好的解决方法

界面介绍

public interface INotifierPropertyChanged : INotifyPropertyChanged
{
void OnPropertyChanged(string property_name);
}

为 PropertyChangedEventHandler 添加新的扩展方法 Raise。然后为这个新接口(interface)添加中介类而不是基本的 INotifyPropertyChanged。

到目前为止,让我们代表其所有者从嵌套对象向您发送消息的代码最少(当所有者需要此类逻辑时)。

感谢大家的帮助和想法。

编辑1

古法写道:

“您不能通过从外部触发事件来导致某事发生,”

这很有趣,因为...我可以。这正是我要问的原因。看一看。

假设您有类字符串。不有趣,对吧?但是让我们用 Invoker 类打包它,它会在每次更改时发送事件。

现在:

class MyClass : INotifyPropertyChanged
{
public SuperString text { get; set; }
}

现在,当文本更改时,MyClass 也会更改。因此,当我在文本中时,我知道,如果只有我拥有所有者,它也会发生变化。所以我可以代表它发送事件。而且它在语义上是 100% 正确的。

备注:我的类只是更聪明一点——所有者设置它是否想要这样的逻辑。

编辑2

传递事件处理程序的想法——“2”将不会显示。

public class Mediator
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property_name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property_name));
}

public void Link(PropertyChangedEventHandler send_through)
{
PropertyChanged += new PropertyChangedEventHandler((obj, args) => {
if (send_through != null)
send_through(obj, args);
});
}

public void Trigger()
{
OnPropertyChanged("hello world");
}
}
public class Sender
{
public event PropertyChangedEventHandler PropertyChanged;

public Sender(Mediator mediator)
{
PropertyChanged += Listener1;
mediator.Link(PropertyChanged);
PropertyChanged += Listener2;

}
public void Listener1(object obj, PropertyChangedEventArgs args)
{
Console.WriteLine("1");
}
public void Listener2(object obj, PropertyChangedEventArgs args)
{
Console.WriteLine("2");
}
}

static void Main(string[] args)
{
var mediator = new Mediator();
var sender = new Sender(mediator);
mediator.Trigger();

Console.WriteLine("EOT");
Console.ReadLine();
}

编辑3

作为对所有关于滥用直接事件调用的争论的评论——滥用当然仍然是可能的。只需实现上述解决方法即可。

编辑4

我的代码的小样本(最终用途),Dan 请看一看:

public class ExperimentManager : INotifierPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property_name)
{
PropertyChanged.Raise(this, property_name);
}


public enum Properties
{
NetworkFileName,
...
}

public NotifierChangedManager<string> NetworkFileNameNotifier;
...

public string NetworkFileName
{
get { return NetworkFileNameNotifier.Value; }
set { NetworkFileNameNotifier.Value = value; }
}

public ExperimentManager()
{
NetworkFileNameNotifier =
NotifierChangedManager<string>.CreateAs(this, Properties.NetworkFileName.ToString());
...
}

最佳答案

在开始咆哮之前先想一想。如果任何方法都可以调用任何对象上的事件,那会不会破坏封装并且也会造成混淆?事件的意义在于,具有事件的类的实例可以通知其他对象某个事件已经发生。事件必须来自那个类,而不是来自任何其他类。否则,事件变得毫无意义,因为任何人都可以在任何时间触发任何对象上的任何事件,这意味着当事件触发时,您不确定它是否真的是因为它所代表的 Action 发生了,或者仅仅是因为某些第 3 方类决定找点乐子。

就是说,如果您希望能够允许某种中介类为您发送事件,只需打开带有添加和删除处理程序的事件声明即可。然后你可以这样做:

public event PropertyChangedEventHandler PropertyChanged {
add {
propertyChangedHelper.PropertyChanged += value;
}
remove {
propertyChangedHelper.PropertyChanged -= value;
}
}

然后 propertyChangedHelper 变量可以是某种对象,它实际上会触发外部类的事件。是的,您仍然需要编写添加和删除处理程序,但它是相当少的,然后您可以使用任何您想要的复杂性的共享实现。

关于c# - 为什么在 C# 中禁止为发件人发送事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3642809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com