Waf*_*Top 10 c# generics comparison delegates
随意质疑我的理智.
我需要确定Action<T>vs Action<T>是否是原始实例.我有一个带有类变量的类,protected Action<T> MessageCallback = null;当我abstract class Message<T>通过抽象方法创建时,我强制"他们"初始化MessageCallBack.此MessageCallback被添加到IList<Action<object>>.此列表中定义的每个操作可以不同.现在,我想要做的是从列表中删除一个特定的操作,但我没有尝试比较它.
以下是我尝试过的最后一次设置的示例:
public void Unsubscribe<TMessage>(Action<TMessage> 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<object>(m =>
messageCallback((TMessage)m)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我明白我想要做的事情可能是不可能的,但一般来说,我只是做一些不正当的事情或缺乏适当的知识来做这件事,就像我想的那样.提前感谢您提供的任何帮助.
比较它们会一直失败.以下3项建议均无效.我相信我可以改变我处理它的方式,并通过传递一个键然后指向单独的列表<key, indexOfAction>然后通过索引删除它来使它成为我需要它的工作方式.但是,我觉得我仍然需要付出很大的努力来解决,所以我将提供更多信息,看看它是否有帮助.
这是清单:
private readonly IDictionary<Type, IList<Action<object>>> messageReceivedCallbacks;
Run Code Online (Sandbox Code Playgroud)
以下是将操作添加到列表的方式:
void AddMessageReceivedCallback<TMessage>(Action<TMessage> messageReceivedCallback)
{
var intermediateReceivedCallback = new Action<object>(m =>
messageReceivedCallback((TMessage)m));
var receivedList = messageReceivedCallbacks.GetOrCreateValue(typeof(TMessage),
() => new List<Action<object>>());
lock (receivedList)
{
receivedList.Add(intermediateReceivedCallback);
}
}
Run Code Online (Sandbox Code Playgroud)
请耐心等待,因为我对这些更先进的编码更新.我可以告诉这阻止我因为new关键字而进行直接实例比较.在上面发布的I(第一个)尝试中,我试图让我的回调与添加它的形式相匹配.这是行不通的.我尝试过比较目标,方法,甚至将每种方法转换为其他类型,然后进行比较.
我决定转换我传递的回调,就像它被添加到最后一个aka:
var callbackConverted = new Action<object>(m =>
messageReceivedCallback((TMessage)m));
Run Code Online (Sandbox Code Playgroud)
接下来,我使用立即窗口来获取一些信息(回调是列表中的一个,callbackConverted是我传入的那个):
callback.Target
{MessageBus.MessageCoordinator.<Tests.MessageBus.TestMessage>}
messageReceivedCallback: {Method = {Void <InitializeMessageCallback>b__0(Tests.MessageBus.TestMessage)}}
callback.Method
{Void <AddMessageReceivedCallback>b__8(System.Object)}
[System.Reflection.RuntimeMethodInfo]: {Void <AddMessageReceivedCallback>b__8(System.Object)}
base {System.Reflection.MethodBase}: {Void <AddMessageReceivedCallback>b__8(System.Object)}
MemberType: Method
ReturnParameter: {Void }
ReturnType: {Name = "Void" FullName = "System.Void"}
ReturnTypeCustomAttributes: {Void }
callbackConverted.Target
{MessageBus.MessageCoordinator.<Tests.MessageBus.TestMessage>}
messageReceivedCallback: {Method = {Void <InitializeMessageCallback>b__0(Tests.MessageBus.TestMessage)}}
messageType: {Name = "TestMessage" FullName = "Tests.MessageBus.TestMessage"}
callbackConverted.Method
{Void <Unsubscribe>b__1d(System.Object)}
[System.Reflection.RuntimeMethodInfo]: {Void <Unsubscribe>b__1d(System.Object)}
base {System.Reflection.MethodBase}: {Void <Unsubscribe>b__1d(System.Object)}
MemberType: Method
ReturnParameter: {Void }
ReturnType: {Name = "Void" FullName = "System.Void"}
ReturnTypeCustomAttributes: {Void }
Run Code Online (Sandbox Code Playgroud)
我希望这些额外信息有所帮助.
我发现我让这太复杂了.我需要做的就是添加我的动作,然后从每个字典中删除(唯一的实例).我正在努力做一些复杂的事情.
目前没有提供任何方法我可以肯定地说,但是我正在标记我认为其他人将使用最佳镜头作为答案.谢谢所有贡献的人.
您是在谈论找到执行相同操作的操作,还是完全相同的实例?如果它是完全相同的实例,您可以使用:
messageReceivedCallbacks[callbackType].Remove(messageCallback);
Run Code Online (Sandbox Code Playgroud)
如果要比较方法体,可以执行以下操作:
private bool ActionComparer<T>(Action<T> firstAction, Action<T> 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<bool> actionOne = (param1) => {return;};
Action<bool> actionTwo = (param2) => {var i = 1; return;};
Action<bool> actionThree = (param1) => {return;};
Action<bool> 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);
Run Code Online (Sandbox Code Playgroud)
结果:
没有编译器优化感谢RenniePet的评论
action one vs two: False
action one vs three: True
action one vs four: False
Run Code Online (Sandbox Code Playgroud)
使用编译器优化
action one vs two: True
action one vs three: True
action one vs four: False
Run Code Online (Sandbox Code Playgroud)
但请注意,第一行和第二行之间的比较