【问题标题】:Generic argument not assignable通用参数不可分配
【发布时间】:2013-10-23 12:28:11
【问题描述】:

我正在使用 C#.NET 3.5。我明白了

参数类型“GenericTest.BarkStrategy”不可分配给参数类型“GenericsTest.IAnimalStrategy”

使用以下(对于这个问题尽可能简化)代码:

using System.Collections.Generic;

namespace GenericsTest {
    class Program {
        static void Main(string[] args) {
            List<IAnimalStrategy<IAnimal>> strategies = 
                new List<IAnimalStrategy<IAnimal>>();
            strategies.Add(new BarkStrategy());
        }
    }

    interface IAnimal { }
    interface IAnimalStrategy<T> where T : IAnimal { }
    class Dog : IAnimal { }
    class BarkStrategy : IAnimalStrategy<Dog> { }
}

【问题讨论】:

标签: c# generics


【解决方案1】:

你必须告诉编译器你的接口是协变的:IAnimalStrategy&lt;out T&gt;

namespace GenericsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            List<IAnimalStrategy<IAnimal>> strategies = new List<IAnimalStrategy<IAnimal>>();
            strategies.Add(new BarkStrategy());
        }
    }

    interface IAnimal { }
    interface IAnimalStrategy<out T> where T : IAnimal { }

    class Dog : IAnimal { }
    class BarkStrategy : IAnimalStrategy<Dog> { }
}

不幸的是,它仅在 C# 4.0 中可用:How is Generic Covariance & Contra-variance Implemented in C# 4.0?

为了理解问题,你可以忘记列表,这行不编译:

IAnimalStrategy<IAnimal> s = new BarkStrategy();

IAnimalStrategy&lt;IAnimal&gt;接口可以在IAnimal上做事,可以设置IAnimal类型的属性

interface IAnimalStrategy<T> where T : IAnimal 
{
    T Animal {get; set;}
}

然后你就可以做类似的事情

IAnimalStrategy<IAnimal> s = new BarkStrategy();
s.Animal = new Cat();

它会吹到你脸上。所以 C#3.5 不允许你这样做。
如果您说 T 与 out 关键字协变,C#4.0 将允许您这样做

interface IAnimalStrategy<out T> where T : IAnimal 
{
    T Animal {get; set;}
}

这又要吹了,

无效方差:类型参数“T”必须在 IAnimalStrategy.Animal'。 'T' 是协变的。

协变和逆变很难理解,我建议你阅读 Eric Lippert 博客上的精彩系列:Covariance and Contravariance in C#

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-01
    • 2018-06-29
    • 2023-03-19
    • 2023-04-02
    • 1970-01-01
    • 2019-07-20
    • 2019-06-24
    • 2021-06-14
    相关资源
    最近更新 更多