链式方法

时间:2011-11-10 22:50:55

标签: c# .net

很久以前,我看到了一些允许你动态链接一系列方法的东西。不记得它是在C#还是C ++中。

它是这样的:

方法:

Foo();
Bar();
Moar();

然后创建一个对象,用于订阅(缺少更好的单词)上述任何或所有方法(取决于程序员的规范),并且传递给此对象的任何内容都将运行所有订阅的方法。

我问,因为我正在为一个程序的内核工作,这取决于各种选择,可能需要或可能不需要某些方法。由于这个程序需要非常紧密地编码(我不想在if / else语句上浪费处理器周期...它会加起来),我想知道是否有人回忆起我试图传达的内容,以及C#是什么相当于。

谢谢, -R

4 个答案:

答案 0 :(得分:3)

听起来就像一个事件:

宣称:

public event Action Something;

订阅:

obj.Something += x.Foo;
...
obj.Something += y.Bar;
...
obj.Something += z.Moar;

然后调用:

protected virtual void OnSomething() {
    var handler = Something;
    if(handler != null) handler();
}
...
OnSomething(); // call ^^^^^^

会调用所有3种方法,但松散耦合。

请注意,只需使用 delagate 而不是事件,您就可以完全相同。另请注意,事件通常具有更具体的void (object sender, SomeEventArgs args)签名(但这是惯例,而非要求)。

答案 1 :(得分:2)

Marc的答案是C#中最接近的答案,但值得指出 - 这不会比一系列if更快,它会更慢。

也许您指的是在方法结束时{(1}}到汇编程序中的另一个地址的方式,以避免JMP和后续的两个CALL - 这是X86汇编程序,但现代优化编译器将为您进行优化。

也就是说,你用RET调用一个方法,将返回地址推送到堆栈,然后在另一个方法的末尾,你可能CALL另一个方法,但是它完成了,做了一个CALL返回第一个结尾,RET跳回原来的来电者。但是,在第一个末尾有一个RET,它'链'到第二个,第二个方法的JMP返回给调用者,节省了额外的跳转/一些堆栈操作。


根据您的目的,您可以使用框架的反射发射部分(http://msdn.microsoft.com/en-us/library/3y322t50.aspx)在.NET中动态生成代码。如果要以文本方式进行操作,还可以使用内置的C#编译器将方法动态编译到内存中。那可以成为你的想法。

答案 2 :(得分:0)

您能否回忆起某些API中“流畅”编码风格的一些片段?

每个函数都返回其对象实例作为函数结果,因此您可以将这样的调用链接在一起:

obj.Foo()
 .Bar()
 .Moar();

这里没有特别神奇的性能提升,它只是让你不必再次输入对象实例变量名。

好的,使用函数result作为下一次调用的实例参数可能会获得非常小的效率。如果函数结果在寄存器EAX中返回,并且下一次调用的实例指针在寄存器EAX中传递,则该流畅调用模式保存一条或两条指令,以将实例指针加载到EAX寄存器中以进行下一次调用。但就性能调整而言,这真的很小。

答案 3 :(得分:0)

您可以使用delegate解决问题