请原谅我这是一个愚蠢的问题,我承认我没有多想过.
但是,您何时愿意使用回调(即传入Func或Action),而不是暴露和使用事件?
UPDATE
这个问题的动机是以下问题:
我有一个ThingsHandler类,可以与ThingEditor关联.ThingsHandler处理事物列表,知道它们的顺序,哪一个是"当前的",添加或删除新的等等.
ThingEditors只能修改一件事.
当用户选择要编辑的新Thing时,ThingsHandler需要提醒ThingEditor,当用户说"完成"时,ThingEditor需要提醒ThingsHandler.
困扰我的是让这两个类彼此引用 - 虽然我猜这是不可避免的 - 或者绑定到两个方向的事件.我想知道在一个方向上使用回调是否"更清洁".
我怀疑这有一种设计模式,并为我的无知(和懒惰)谦卑地道歉.
Eri*_*ert 28
虽然到目前为止其他答案看似合理,但我会采取更具哲学性的方法.
类是一个机制,即模型有一种特殊的东西在一个特定的领域.编写类的内部细节以将机制的实现细节与正在建模的语义混淆时非常容易.我的意思的一个简短例子:
class Giraffe : Mammal, IDisposable
{
public override void Eat(Food f) { ... }
public void Dispose() { ... }
}
Run Code Online (Sandbox Code Playgroud)
请注意我们如何将现实世界的物体(长颈鹿是一种哺乳动物,长颈鹿吃食物)与实施细节混为一谈(长颈鹿的一个实例是一个可以用"使用"处理的物体. "声明".我保证,如果你去动物园,你将永远不会看到长颈鹿被处理使用声明.我们把这里的水平搞混了,这是不幸的.
我尝试使用事件(和属性)作为语义模型的一部分,并使用回调方法(和字段)作为机制的一部分.我会让GaveBirth成为长颈鹿的事件,因为这是我们试图捕捉的真实世界长颈鹿行为模型的一部分.如果我有一些机制,比如说,我想实现一个顺序遍历树遍历算法,它走遍了长颈鹿的家谱,并在每一个上调用一个方法,那么我会说这显然是一个机制,而不是一部分该模型,并使其成为一个回调,而不是试图将其塞进事件模型中.
Mar*_*ell 27
我使用回调在少数情况下,我知道,它只会不断开火一次,回调是具体到一个方法调用(而不是一个对象实例) -例如,作为异步方法的返回部分.
对于静态实用程序方法尤其如此(因为您没有实例,并且在不小心使用并且要避免时静态事件是致命的),但当然另一种选择是使用事件创建类实例.
Cod*_*uth 23
通常,如果需要,我使用回调,而当它应该是可选的时使用事件.如果您期望总是听某事,请不要公开活动.
考虑以下:
public class MyClass_Event
{
public event EventHandler MakeMeDoWork;
public void DoWork()
{
if (MakeMeDoWork == null)
throw new Exception("Set the event MakeMeDoWork before calling this method.");
MakeMeDoWork(this, EventArgs.Empty);
}
}
Run Code Online (Sandbox Code Playgroud)
与:
public class MyClass_Callback
{
public void DoWork(EventHandler callback)
{
if (callback == null)
throw new ArgumentException("Set the callback.", "callback"); // better design
callback(this, EventArgs.Empty);
}
}
Run Code Online (Sandbox Code Playgroud)
代码几乎与回调可以作为null传递相同,但至少抛出的异常可能更相关.
就面向对象设计和类耦合而言,回调接口和事件之间没有太大区别。
然而,我更喜欢类需要向有兴趣监听的人“大喊大叫”的事件(通常是多个事件)以及特定类请求异步操作的回调。
无论您使用什么,请在整个代码库中一致地使用它们!
一个例子是回调何时应返回某些内容。例如(愚蠢的例子):
public int Sum(Func<int> callbackA, Func<int> callbackB) {
return callbackA() + callbackB();
}
public void UseSum() {
return sum(() => 10, () => 20);
}
Run Code Online (Sandbox Code Playgroud)