我正在尝试从Django(http://docs.djangoproject.com/en/dev/topics/signals/)或其在C#中的概念实现信号,以减少/消除耦合/方法依赖性。
到目前为止,我正在复制代码,直到我意识到方法不是C#中的对象,就像在Python中一样。然后我想到了指针,然后我意识到我不能指向方法。它的C#版本是代理。
然后我意识到代理人有一个独特的签名,所以我不能真正将委托方法(带有差异签名)混合到List中,或者我可以吗?
我做了一些谷歌搜索,发现了Reactive LINQ,到目前为止,linq看起来很棒,但我还是不知道何时使用它们。
所以我的问题是,你如何在C#中实现Signals概念?谢谢!
哦,我提到我是新的(1天)到C#?我确实有各种其他语言的背景,包括Java / C / Python。
干杯:)
答案 0 :(得分:2)
您在这里谈论的内容通常作为C#中的事件处理,例如;
public class SomeType {
public event EventHandler SomeEvent;
protected virtual void OnSomeEvent() {
EventHandler handler = SomeEvent;
if(handler!=null) handler(this,EventArgs.Empty);
}
public void SomethingInteresting() {
// blah
OnSomeEvent(); // notify subscribers
// blap
}
// ...
}
订阅者......
SomeType obj = new SomeType();
//...
obj.SomeEvent += /* some handler */
//...
处理程序可以是一种方法,但在您对签名等的讨论中,使用不匹配签名重用现有方法的常用方法是使用匿名方法:
obj.SomeEvent += delegate { this.Text = "Done!"; };
你可以有一个代表列表:
List<SomeDelegateType> list = new List<SomeDelegateType>();
list.Add(...);
但这可能是多余的,因为委托实例是多播 - 因此您可以更直接地执行此操作:
Action action = null;
action += delegate { Console.WriteLine("Did A");};
action += delegate { Console.WriteLine("Did B");};
action(); // does both A & B
请注意,更复杂的委托使用可能涉及传入的参数值 - 例如:
int i = 24;
Func<int,int,int> func = (x,y) => (x * i) + y;
int result = func(2, 3); // 51
通过将匿名方法(或lambdas,如上所述)与捕获的变量结合起来,签名必须匹配的问题很少成为问题 - 您可以使用lambda进行包装以使签名匹配(添加额外的值或删除参数,根据需要)。
请注意,对于事件(特别是),常见的方法是保留签名:
void SomeDelegateType(object sender, SomeArgsType args);
其中SomeArgsType : EventArgs
- 或者使用EventHandler<T>
来为您执行此操作。