【问题标题】:Interface with generic object of the interface type [duplicate]具有接口类型的通用对象的接口[重复]
【发布时间】:2013-10-22 09:52:29
【问题描述】:

我有如下界面:

public interface IObject
{
    double x { get; }
    double y { get; }
    Holder<IObject> Holder { get; set; }
}

还有这个类

public class Holder<T> where T : IObject 
{
  private List<T> items; 
  public void AddItem(T item){
     items.Add(item);
     item.Holder = this;
}

但是编译器不喜欢 AddItem 方法并且在这一行:

item.Holder = this;

给我这个错误:

Cannot convert source type 'Holder<T>' to target type 'Holder<IObject>'

为什么我不能这样做?对于这种情况有什么好的解决方案? 谢谢

【问题讨论】:

  • 为什么不使用公共类 Holder
  • 为什么同一个问题问了两次?
  • 这不是同一个问题,我在上一个问题上有太多错误,所以我写了一个新问题。这也是另一种情况。

标签: c# .net interface


【解决方案1】:

你必须记住 Genrics 在 C# 中的工作方式,编译器创建一个指定类型的类,因此你有错误。

为了解释更多,举个例子:

public class InterfaceImplementation : IObject
{
}

然后是你做的一些地方:

var genericInitialisation = new Holder<InterfaceImplementation>();

编译器在编译时将创建一个类HolderInterfaceImplementation 替换T 泛型参数的所有精度。

所以编译后你将拥有这个类:

public class HolderInterfaceImplementation
{
  private ListInterfaceImplementation items; 
  public void AddItem(InterfaceImplementation item){
     items.Add(item);
     item.Holder = this;
}

item.Holder 将是HolderIObject 类型,因此编译器会报告无法将HolderInterfaceImplementation 转换为HolderIObject 的错误,这是合乎逻辑的。

解释理论后,解决方案自然而然,这里是一个例子:

    public interface IObject<T> where T : IObject<T>
    {
      double x { get; }
      double y { get; }
      Holder<T> Holder { get; set; }
    }


    public class Holder<T> where T : IObject<T>
    {
      public Holder()
      {
        items = new List<T>();
      }
      private List<T> items;
      public void AddItem(T item)
      {
        items.Add(item);
        item.Holder = this;
      }
    }

    public class Implementation : IObject<Implementation>
    {

      public double x
      {
        get { return 0; }
      }

      public double y
      {
        get { return 0; }
      }

      public Holder<Implementation> Holder
      {
        get;
        set;
      }
    }
    static void Main(string[] args)
    {
      var t = new Holder<Implementation>();
      t.AddItem(new Implementation());
      Console.ReadKey();
    }

【讨论】:

  • 很棒的详细答案,谢谢。
【解决方案2】:

如果可以转换那将是一个类型系统漏洞:

public class Holder<T> where T : IObject 
{
  public T SomeField;
}
...
var holder = new Holder<IObjectSubType2>();
Holder<IObject> dummy = holder; //assuming that this works
dummy.SomeField = new IObjectSubType1(); //violates type safety
IObjectSubType2 converted = holder.SomeField;

如您所见,我能够将IObjectSubType1 的实例转换为IObjectSubType2

这就是为什么 this 不进行类型检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多