【问题标题】:Cannot assign Action<TDerivedThing> to Action<IThing>无法将 Action<TDerivedThing> 分配给 Action<IThing>
【发布时间】:2013-04-17 13:20:24
【问题描述】:

我有以下类定义:

public class Registry
{
     private List<Action<IThing>> _thingActions = new List<Action<IThing>>();

     public Register<TDerivedThing>(Action<TDerivedThing> thingAction)
          where TDerivedThing : IThing
     {
        // this line causes compilation issue
        _thingActions.Add(thingAction);
     }     
}

为什么这抱怨它不能将Action&lt;TDerivedThing&gt;分配给Action&lt;IThing&gt;,我应该如何解决这个问题?

【问题讨论】:

  • 你不能,这不是类型安全的。
  • 愚蠢的问题。 TDerivedThing 是否实现了接口?
  • 这是一个协方差限制。见这里:stackoverflow.com/questions/1078423/…
  • 大概你要遍历_thingActions 在一些IThing 上运行它们?当您的 IThing 不是 TDerivedThing 时会发生什么?
  • @StianStandahl 它确实......应该在哪里表示

标签: c#


【解决方案1】:

如果 C# 允许您这样做,那么这样的代码将是有效的:

interface IFruit {
    void Eat();
}

class Apple : IFruit {
    // ...
    void EatApple();
}

class Pear : IFruit {
    // ...
    void EatPear();
}

void EatApple(Apple a) {
    a.EatApple();
}

void EatPear(Pear p) {
    p.EatPear();
}

Action<IFruit> fruitAction = EatApple;
fruitAction(new Pear()); // Calls EatApple(new Pear())

演员表是无效的,因为它不应该是,你不应该首先尝试这样做。您的IThing 操作列表所有必须是接受任何结果的操作。

【讨论】:

    【解决方案2】:

    当然不是,List&lt;EventArgs&gt; 也不能分配给 List&lt;object&gt;,即使 EventArgs 是一个对象。

     public void Register<TDerivedThing>(Action<TDerivedThing> thingAction)
          where TDerivedThing : IThing
     {
        _thingActions.Add(t => thingAction(t as TDerivedThing));
     }
    

    可能是一个解决方案,但我不知道您的应用程序。

    【讨论】:

    • 这就是我发布它的原因! ;-)
    【解决方案3】:

    这是一个协方差和逆变问题。我建议您阅读有关它的msdn article。它为您的问题提供了完整的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      相关资源
      最近更新 更多