C# 链式方法
很久以前,我看到了一些东西,它允许您动态地将一系列方法链接在一起。不记得是C,还是C++?< /P> 事情是这样的:C# 链式方法,c#,.net,C#,.net,很久以前,我看到了一些东西,它允许您动态地将一系列方法链接在一起。不记得是C,还是C++?< /P> 事情是这样的: obj.Foo() .Bar() .Moar(); 方法: Foo(); Bar(); Moar(); 然后创建一个订阅(因为没有更好的词)上述任何或所有方法(取决于程序员的规范)的对象,传入该对象的任何内容都将通过所有订阅的方法运行 我这样问是因为我正在为一个程序开发一个内核,它取决于各种选择,可能需要也可能不需要某些方法。由于这个程序需要非常严格的编码(我不希望在if
obj.Foo()
.Bar()
.Moar();
方法:
Foo();
Bar();
Moar();
然后创建一个订阅(因为没有更好的词)上述任何或所有方法(取决于程序员的规范)的对象,传入该对象的任何内容都将通过所有订阅的方法运行
我这样问是因为我正在为一个程序开发一个内核,它取决于各种选择,可能需要也可能不需要某些方法。由于这个程序需要非常严格的编码(我不希望在if/else语句上浪费处理器周期……它会累加起来),我想知道是否有人记得我试图传达的内容,以及C#等价物是什么
谢谢,
-R听起来像是一个事件:
声明:
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(objectsender,SomeEventArgs args)
签名(但这是惯例,不是要求)。听起来像是一个事件:
声明:
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(objectsender,SomeEventArgs-args)
签名(但这是惯例,不是要求)。Marc的答案是C#中最接近的,但值得指出的是,这不会比一系列的签名快,如果的话,它会更慢
也许您指的是在方法末尾将JMP
转到汇编程序中另一个地址的方法,以避免调用和两个后续的RET
s,这就是X86汇编程序,但是现代优化编译器将为您进行优化
例如,您使用call
调用一个方法,该方法将返回地址推送到堆栈中,然后在另一个方法的末尾,您可以调用另一个方法,但它完成后,执行RET
返回到第一个方法的末尾,执行RET
跳回原始调用方。但是,如果在第一个方法的末尾有一个JMP
,它将链接到第二个方法,而第二个方法的RET
将返回给调用方,从而节省额外的跳转/一些堆栈操作
根据您想要执行的操作,您可以使用框架()的反射发射部分在.NET中动态生成代码。如果您想以文本方式将方法编译到内存中,还可以使用内置的C#编译器将方法动态编译到内存中。这可能就是你所想的。马克的答案是C#中最接近的答案,但值得指出的是,这不会比一系列的快,如果s,速度会慢一些
也许您指的是在方法末尾将JMP
转到汇编程序中另一个地址的方法,以避免调用和两个后续的RET
s,这就是X86汇编程序,但是现代优化编译器将为您进行优化
例如,您使用call
调用一个方法,该方法将返回地址推送到堆栈中,然后在另一个方法的末尾,您可以调用另一个方法,但它完成后,执行RET
返回到第一个方法的末尾,执行RET
跳回原始调用方。但是,如果在第一个方法的末尾有一个JMP
,它将链接到第二个方法,而第二个方法的RET
将返回给调用方,从而节省额外的跳转/一些堆栈操作
根据您想要执行的操作,您可以使用框架()的反射发射部分在.NET中动态生成代码。如果您想以文本方式将方法编译到内存中,还可以使用内置的C#编译器将方法动态编译到内存中。这可能就是你所想的。你能回忆起一些API中“流畅”编码风格的片段吗
每个函数都将其对象实例作为函数结果返回,因此您可以像这样将调用链接在一起:
obj.Foo()
.Bar()
.Moar();
这里没有特别神奇的性能提升,它只是让您不必反复键入对象实例变量名
好的,使用函数result作为下一次调用的实例参数可能会获得很小的效率。如果函数结果在寄存器EAX中返回,下一次调用的实例指针在寄存器EAX中传递,那么此流畅调用模式将保存一条或两条指令,以便将实例指针加载到EAX寄存器中,以便下一次调用。但就性能调整而言,这确实是一个很小的问题。您能回忆一下一些API中的“流畅”编码风格的片段吗
每个函数都将其对象实例作为函数结果返回,因此您可以像这样将调用链接在一起:
obj.Foo()
.Bar()
.Moar();
这里没有特别神奇的性能提升,它只是让您不必反复键入对象实例变量名
好的,使用函数result作为下一次调用的实例参数可能会获得很小的效率。如果函数结果在寄存器EAX中返回,下一次调用的实例指针在寄存器EAX中传递,那么此流畅调用模式将保存一条或两条指令,以便将实例指针加载到EAX寄存器中,以便下一次调用。但是,就性能调整而言,这确实很小。您可以使用委托解决它您可以使用委托解决它您知道每秒有数十亿个处理器周期吗?除非你愿意,否则你不会浪费它们