在 C# 中覆盖泛型约束

时间:2021-01-20 22:57:55

标签: c# generics

如果这更适合软件工程堆栈交换,我深表歉意,但由于这是相当特定于语言的,我相信我是在正确的地方提问。

我有一个项目,涉及将相当大的代码库从 Java 转换为 C#。原始 Java 项目的接口大致相当于以下 C# 代码段。

public interface IEntry<out T> where T : class, IEntry<T>{
  T SetName(string nameIn);

  string GetName();
}

它还包含此接口的基本实现。

public abstract class BaseEntry<T> : IEntry<T> where T : BaseEntry<T>{
  private string name;
  internal object extraData;

  public T SetName(string nameIn){
    name = nameIn;
    return (T)this;
  }

  public string GetName(){
    return name;
  }
}

问题出现在包含实现 IEntry<T> 接口的类型条目的类中。

public class ObjectHolder<T> where T : class, IEntry<T>{
  private readonly List<T> entries;
  private readonly bool canGetExtraData;

  public ObjectHolder(){
    //HasGenericBaseType simply checks if the first type implements the second type
    canGetExtraData = HasGenericBaseType(typeof(T), typeof(BaseEntry<>));
  }

  public void Add(T entry){
    entries.Add(entry);
  }

  public void DoSomething(int index){
    if(!canGetExtraData){
      T entry = entries[index];
      object extraData = ((BaseEntry<T>)entry).extraData; <-- This cast fails on compilation
      //Something gets done with the extraData object
    }
  }
}

指示的行在编译时给了我以下错误。

error CS0314: The type `T' cannot be used as type parameter `T' in the generic type or method `BaseEntry<T>'. There is no boxing or type parameter conversion from `T' to `BaseEntry<T>'

我明白为什么会出现此错误,但我正在努力寻找解决方法。如何重新设计上述类以允许访问扩展 BaseEntry<T> 的类型的内部对象字段?

1 个答案:

答案 0 :(得分:1)

所以基本上BaseEntry<T>不等于IEntry<T>

类比:您有一个实现 MammalILegs,但并非所有具有 ILegs 的都是 Mammal

您可能想要查看的修复程序很少,要么将 extraData 推回 IEntry<T>,要么按照 @JeremyLakeman 的建议,创建一个单独的通用或/非通用 IExtraData 的接口并受其约束。答案取决于 IEntry<T> 是否总是有额外数据。

相关问题