Interface with generic object of the interface type [duplicate]

北城以北 提交于 2019-12-25 16:31:09

问题


I have the following interface:

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

and this class

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

However the compiler doesn't like the AddItem method and on this line :

item.Holder = this;

gives me this error:

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

Why can't I do it and what is a good solution for this scenario? thank you


回答1:


You have to bear in mind the way Genrics works in C#, The compiler create a class of the specified type, and because of that you have the error.

To explain more, given the following example:

public class InterfaceImplementation : IObject
{
}

and then some where you do :

var genericInitialisation = new Holder<InterfaceImplementation>();

The compiler at compile time will create a class HolderInterfaceImplementation replacing all accurances of the T generic parameter.

so after compilation you will have this class:

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

And item.Holder would be HolderIObject type, so the compiler report an error about not being able to convert HolderInterfaceImplementation to HolderIObject wich is logical.

After explaining the theory the solution comes naturaly and here is an example:

    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:


If it was possible to convert that would be a type system hole:

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;

As you can see I was able to convert an instance of IObjectSubType1 to an IObjectSubType2.

That's why this does not type check.



来源:https://stackoverflow.com/questions/19514499/interface-with-generic-object-of-the-interface-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!