gpt4 book ai didi

c# - 将通用 Action 委托(delegate)添加到列表

转载 作者:可可西里 更新时间:2023-11-01 08:19:28 26 4
gpt4 key购买 nike

是否可以将通用委托(delegate)操作添加到列表集合中?我需要某种用于 Silverlight 应用程序的简单消息传递系统。

更新以下是我真正“想要”的

class SomeClass<T>
{
public T Data { get; set; }
// and more ....
}

class App
{
List<Action<SomeClass<T>>> _actions = new List<Action<SomeClass<T>>>();

void Add<T>( Action<SomeClass<T>> foo )
{
_actions.Add( foo );
}
}

编译器:

The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

截取初始代码 类 SomeClassBase { }

class SomeClass<T> : SomeClassBase
{
public T Data { get; set; }
// and more ....
}

class App
{
List<Action<SomeClassBase>> _actions = new List<Action<SomeClassBase>>();

void Add<T>( Action<SomeClass<T>> foo )
where T : SomeClassBase
{
_actions.Add( foo );
}
}

编译器提示 - 对于 _actions.Add() 行;

Argument 1: cannot convert from 'System.Action<test.SomeClass<T>>' to 'System.Action<test.SomeClassBase>'
The best overloaded method match for 'System.Collections.Generic.List<System.Action<test.SomeClassBase>>.Add(System.Action<test.SomeClassBase>)' has some invalid arguments

从应用程序方面看,不需要 SomeClassBase 类,但似乎不可能定义 Action<SomeClass<T>> 的列表。元素和基类的方法在使用列表中的类而不是操作时有效

谢谢, 乔臣

最佳答案

编辑:好的,现在我明白您要做什么了。我为后代留下了下面的旧答案:)

不幸的是,您无法在 C# 泛型中表达您想要的关系,但由于您可以确保您是唯一一个操作集合的人,因此您可以自己保证它的安全:

试试这个:

class App
{
private readonly Dictionary<Type, object> delegateMap;

void Add<T>(Action<SomeClass<T>> foo)
{
object tmp;
if (!delegateMap.TryGetValue(typeof(T), out tmp))
{
tmp = new List<Action<SomeClass<T>>>();
delegateMap[typeof(t)] = tmp;
}
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
list.Add(foo);
}

void InvokeActions<T>(SomeClass<T> item)
{
object tmp;
if (delegateMap.TryGetValue(typeof(T), out tmp))
{
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
foreach (var action in list)
{
action(item);
}
}
}
}

请注意,您可以使用委托(delegate)是多播的事实来仅保留 Dictionary<Type, Delegate>并将它们组合在一起,但我会将其作为练习留给读者:)


旧答案

它的失败是有充分理由的。让我们摆脱泛型(因为它们在这里无关紧要)并考虑一个更简单的案例 - 水果和香蕉。

您正在尝试添加 Action<Banana>List<Action<Fruit>> .你不能那样做 - 即使使用 C# 4 的通用变体。为什么?因为不安全。考虑一下:

Action<Banana> peeler = banana => banana.Peel();
List<Action<Fruit>> fruitActions = new List<Action<Fruit>>();
fruitActions.Add(peeler); // Nope!
fruitActions[0].Invoke(new Strawberry());

哎呀!现在我们有一个香蕉削皮器试图给草莓削皮……真是一团糟!

并不是说 其他 方法在 C# 4 中是可以接受的:

Action<Fruit> eater = fruit => fruit.Eat();
List<Action<Banana>> bananaActions = new List<Action<Banana>>();
fruitActions.Add(eater); // Yes!
fruitActions[0].Invoke(new Banana());

这里我们添加一个 Action<Fruit>List<Action<Banana>> - 这是可以接受的,因为你可以对 Action<Banana> 做任何事情对 Action<Fruit> 也有效.

关于c# - 将通用 Action<T> 委托(delegate)添加到列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3319447/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com