C# 泛型:CS0311 在实现满足泛型接口协定的泛型类时

本文关键字:泛型类 泛型接口 满足 泛型 CS0311 实现 | 更新日期: 2023-09-27 18:30:27

我四处搜索并找到了一个有点相关的答案,但是,对于我的生活,我仍然无法弄清楚我哪里出错了!我正在尝试使用类似于下面的代码实现一些通用类型的树数据结构,但我收到编译器错误 CS0311。

错误 CS0311:类型"Test.TestType"不能用作泛型类型或方法"Test.TreeIndex"中的类型参数"K"。没有从"Test.TestType"到"Test.IIndexable"的隐式引用转换。

我只是想不通为什么编译器不知道如何处理这个问题,所以任何线索将不胜感激。

public interface IIndexable<K> where K : IComparable
{
    byte[] ToBytes();
    K FromBytes(byte[] bytes);
}
public class TestType : IIndexable<byte>, IComparable
{
    public int CompareTo(object b)
    {
        return 1;
    }
    public byte[] ToBytes()
    {
        return new byte[1];
    }
    public byte FromBytes(byte[] bytes)
    {
        return 0;
    }
}
public class TreeIndex<K> where K : IComparable, IIndexable<K>
{
    public int SomeMethod(K a, K b)
    {
        return a.CompareTo(b);
    }
}
class Program
{
    static void Main()
    {
        TreeIndex<TestType> treeIndex = new TreeIndex<TestType>(); // CS0311 generated twice here
    }
}

C# 泛型:CS0311 在实现满足泛型接口协定的泛型类时

你的TreeIndex<K>类需要实现K IIndexable<K>,所以TestType应该实现IIndexable<TestType>而不是IIndexable<byte>

public class TestType : IIndexable<TestType>, IComparable
{
    public int CompareTo(object b)
    {
        return 1;
    }
    public byte[] ToBytes()
    {
        return new byte[1];
    }
    public TestType FromBytes(byte[] bytes)
    {
        //...
    }
}

您可能还需要考虑在IIndexable<K>接口上使用通用IComparable<T>约束,即

public interface IIndexable<K> where K : IComparable<K>
{
    byte[] ToBytes();
    K FromBytes(byte[] bytes);
}

由于您有以下通用约束

public class TreeIndex<K> where K : IComparable, IIndexable<K>

而你正在宣布 TreeIndex<TestType>

你是说TestType实现了IIndexable<TestType>,这不可能是真的。

来自 Compiler Error CS0311

当约束应用于泛型类型参数时,隐式 标识或引用转换必须存在于具体参数中 到约束的类型。更正此错误

更改用于创建类的参数。

  • 更改用于创建类的参数。
  • 如果您拥有该类,则可以删除约束或执行某些操作来启用隐式引用或标识转换。为 例如,可以使第二个类型继承第一个类型

基于此,TreeIndex<K>类必须实现IIndexable<TestType>而不是IIndexable<byte>

当你编写TreeIndex<TestType>编译器会询问IIndexable<K>这意味着IIndexable<TestType>你的案例。

但是您的TestType类没有实现IIndexable<TestType>。它实现了IIndexable<byte> .

你告诉编译器做一个new TreeIndex<TestType>()

TreeIndex 的定义是TreeIndex<K> where K : IComparable, IIndexable<K>这意味着您为泛型传递的类型必须是 IIndexable<K>

所以当你说:TreeIndex<TestType>那么编译器期望TestType是类型 IIndexable<K> ,其中KTestType,所以它期望TestType实现IIndexable<TestType>,但它没有。它改为实现IIndexable<byte>


很难说出最适合您的情况的解决方案是什么,但解决它的一种方法是指定 2 个泛型:

// change the TreeIndex definition to take 2 generic types
public class TreeIndex<K, Y>
    where K : IComparable, IIndexable<Y>
    where Y : IComparable
...
// specify both generic types
TreeIndex<TestType, byte> treeIndex = new TreeIndex<TestType, byte>();