c# – 将通用Action代理添加到列表

前端之家收集整理的这篇文章主要介绍了c# – 将通用Action代理添加到列表前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
是否可以向List集合添加一个通用委托Action?
我需要一些Silverlight应用程序的简单消息系统.

UPDATE
以下是我真的“想要”

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类,但是似乎不可能定义一个动作列表< SomeClass< T>>元素和基类的方法在List中使用类时,而不是Action

谢谢,
约亨

解决方法

编辑:好的,现在我看看你要做什么我已经把下面的旧答案留给了后代:)

不幸的是,您无法在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);
             }
         }
     }
}

请注意,您可以使用代理组播的事实,只需保留Dictionary< Type,Delegate>并将它们组合在一起,但是我会把它作为读者的一个练习:)

老回答

这是一个很好的理由是失败的让我们摆脱仿制药(因为它们在这里无关紧要),想想一个更简单的例子 – 水果和香蕉.

您正在尝试添加一个Action< Banana>到列表<动作< 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>到列表<动作&& Banana>> – 这是可以接受的,因为你可以对“行动&香蕉”做任何事情也适用于Action< Fruit>.

猜你在找的C#相关文章