比较代表行动

随意质疑我的理智。

我需要确定Action vs Action是否是原始实例。 我所拥有的是一个带有类变量的类protected Action MessageCallback = null; 当我的abstract class Message是通过抽象方法创建的时候,我强制“他们”初始化MessageCallBack。 此MessageCallback被添加到IList<Action> 。 此列表中定义的每个操作可以不同。 现在,我想要做的是从列表中删除一个特定的操作,但我没有尝试比较它。

以下是我尝试过的最后一次设置的示例:

 public void Unsubscribe(Action messageCallback) { var messageType = typeof(TMessage); var callbackTypes = messageReceivedCallbacks .Keys .Where(k => k.IsAssignableFrom(messageType)); lock (messageReceivedCallbacks) { foreach (var callbackType in callbackTypes) { messageReceivedCallbacks[callbackType].Remove(new Action(m => messageCallback((TMessage)m))); } } } 

我明白我想要做的事情可能是不可能的,但一般来说,我只是做一些不正当的事情,或者缺乏适当的知识,就像我想的那样。 提前感谢您提供的任何帮助。

      • 尝试以下一些方法后更新:

比较他们一直在失败。 以下3项建议都不起作用。 我相信我可以改变我处理它的方式,并通过传入一个键然后指向单独的然后通过索引删除它来使它成为我需要它的工作方式。 但是,我觉得我仍然需要付出这么大的努力来解决,所以我将提供更多信息,看看它是否有帮助。

这是清单:

 private readonly IDictionary<Type, IList<Action>> messageReceivedCallbacks; 

以下是将操作添加到列表的方式:

 void AddMessageReceivedCallback(Action messageReceivedCallback) { var intermediateReceivedCallback = new Action(m => messageReceivedCallback((TMessage)m)); var receivedList = messageReceivedCallbacks.GetOrCreateValue(typeof(TMessage), () => new List<Action>()); lock (receivedList) { receivedList.Add(intermediateReceivedCallback); } } 

请耐心等待,因为我对这些更高级的编码更新。 我可以告诉这可以防止我因为new关键字而进行直接实例比较。 在上面发布的I(第一个)尝试中,我试图让我的回调与添加它的forms相匹配。 这是行不通的。 我尝试过比较目标,方法,甚至将每种方法转换为其他类型,然后进行比较。

我决定转换我传递的回调,就像它被添加到最后一个aka:

 var callbackConverted = new Action(m => messageReceivedCallback((TMessage)m)); 

接下来,我使用立即窗口获取一些信息(回调是列表中的一个,callbackConverted是我传入的那个):

 callback.Target {MessageBus.MessageCoordinator.} messageReceivedCallback: {Method = {Void b__0(Tests.MessageBus.TestMessage)}} callback.Method {Void b__8(System.Object)} [System.Reflection.RuntimeMethodInfo]: {Void b__8(System.Object)} base {System.Reflection.MethodBase}: {Void b__8(System.Object)} MemberType: Method ReturnParameter: {Void } ReturnType: {Name = "Void" FullName = "System.Void"} ReturnTypeCustomAttributes: {Void } callbackConverted.Target {MessageBus.MessageCoordinator.} messageReceivedCallback: {Method = {Void b__0(Tests.MessageBus.TestMessage)}} messageType: {Name = "TestMessage" FullName = "Tests.MessageBus.TestMessage"} callbackConverted.Method {Void b__1d(System.Object)} [System.Reflection.RuntimeMethodInfo]: {Void b__1d(System.Object)} base {System.Reflection.MethodBase}: {Void b__1d(System.Object)} MemberType: Method ReturnParameter: {Void } ReturnType: {Name = "Void" FullName = "System.Void"} ReturnTypeCustomAttributes: {Void } 

我希望这些额外信息有所帮助。

      • **更新

我发现我让这太复杂了。 我需要做的就是关键添加我的动作然后从每个字典中删除(它的唯一实例)。 我正在努力做一些复杂的事情。

目前没有提供任何方法我可以肯定地说,但是我正在标记我认为其他人将使用最佳镜头作为答案。 谢谢所有贡献的人。

您是在谈论找到执行相同操作的操作,还是完全相同的实例? 如果它是完全相同的实例,您可以使用:

 messageReceivedCallbacks[callbackType].Remove(messageCallback); 

如果要比较方法体,可以执行以下操作:

 private bool ActionComparer(Action firstAction, Action secondAction) { if(firstAction.Target != secondAction.Target) return false; var firstMethodBody = firstAction.Method.GetMethodBody().GetILAsByteArray(); var secondMethodBody = secondAction.Method.GetMethodBody().GetILAsByteArray(); if(firstMethodBody.Length != secondMethodBody.Length) return false; for(var i = 0; i < firstMethodBody.Length; i++) { if(firstMethodBody[i] != secondMethodBody[i]) return false; } return true; } Action actionOne = (param1) => {return;}; Action actionTwo = (param2) => {var i = 1; return;}; Action actionThree = (param1) => {return;}; Action actionFour = (param2) => {Thread.Sleep(1); return;}; var areEqualOneTwo = ActionComparer(actionOne, actionTwo); var areEqualOneThree = ActionComparer(actionOne, actionThree); var areEqualOneFour = ActionComparer(actionOne, actionFour); Console.WriteLine("action one vs two: " + areEqualOneTwo); Console.WriteLine("action one vs three: " + areEqualOneThree); Console.WriteLine("action one vs four: " + areEqualOneFour); 

结果:

没有编译器优化感谢RenniePet的评论

 action one vs two: False action one vs three: True action one vs four: False 

使用编译器优化

 action one vs two: True action one vs three: True action one vs four: False 

但请注意,第一行和第二行之间的比较

这会有用吗?

 messageReceivedCallbacks[callbackType].Remove(messageReceivedCallbacks[callbackType].FirstOrDefault(x => x.Target == messageCallback.Target && x.Method == messageCallback.Method)); 

要确定两个委托是否相同,您只需要比较方法和目标对象:

 var list = messageReceivedCallbacks[callbackType]; for (var i = list.Count-1; i >= 0; i--) if (list[i].Method == messageCallback.Method && list[i].Target == messageCallback.Target) list.RemoveAt(i);