Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic class implementing interface fails

Tags:

c#

A meet a strange problem at compimation saying that a class does not implement an interface.

Lets say a v got a class:

public Class MyClass
{
...
}

And an interace:

public Interface IMyInterface
{
 MyClass PropertyOfMyClass {get;}
}

and now a generic class:

public class MyGeneric<T> where T:MyClass
{
  T PropertyOfMyClass 
  {
    get{return ...;}
  }
}

Until here everythings fine and compiles right.

But this will break at compilation time:

public class MyGeneric<T>:IMyInterace where T:MyClass
    {
      T PropertyOfMyClass 
      {
        get{return ...;}
      }
    }

Saying that MyGeneric does not implements method of IMyInterface. But obviously it does, not ?

like image 680
Pitming Avatar asked Apr 22 '10 08:04

Pitming


2 Answers

You can't implement properties (or methods) from interfaces with variance. This doesn't just affect generics. For example:

public interface IFoo
{
    object Bar();
}

public class Foo : IFoo
{
    // This won't compile
    string Bar() { return "hello"; }
}

Now you can get round this with explicit interface implementation:

public class Foo : IFoo
{
    // Make the interface implementation call the more strongly-typed method
    object IFoo.Bar() { return Bar(); }

    string Bar() { return "hello"; }
}

That may be an answer for you - or it may not. We'd need to know exactly why you wanted to declare the property as being of type T rather than just MyClass to know for sure.

like image 51
Jon Skeet Avatar answered Oct 13 '22 00:10

Jon Skeet


Another workaround would be to make the interface generic itself :

public interface IMyInterface<T> where T : MyClass
{
    T PropertyOfMyClass { get; }
}

You can then use it on a class :

public class MyGenericClass<T> : IMyInterface<T> where T : MyClass
{
    T PropertyOfMyClass 
    { 
        get { ... } 
    }
}

Note that using this implementation, the constraint on T in the generic class can be different from the one on the interface, as long as it ensures the interface constraint is respected :

public class MyOtherClass : MyClass
{
}

public class MyOtherGenericClass<T> : IMyInterface<T> where T : MyOtherClass
{
    T PropertyOfMyClass
    {
        get { ... }
    }
}
like image 21
Thibault Falise Avatar answered Oct 12 '22 23:10

Thibault Falise