16

Bit surprised why this does not work

Is this a limitation of the compiler or does it make good sense not to support it?

public class Class1<T> : IInterface
    where T : Test2
{
    public T Test { get; private set; }
}

public class Test2
{
}

internal interface IInterface
{
    Test2 Test { get; }
}

The error I get is

'ClassLibrary1.Class1<T>' does not implement interface member 'ClassLibrary1.IInterface.Test'. 
'ClassLibrary1.Class1<T>.Test' cannot implement 'ClassLibrary1.IInterface.Test' because it does not have the matching return type of 'ClassLibrary1.Test2'.
3
  • See also stackoverflow.com/questions/5709034/… Commented Oct 10, 2012 at 11:28
  • Why does Class1 need to be generic? If return type of Test is Test2, then make it return this type and you're done. You will be able to return any types derived from Test2 anyway. Commented Oct 10, 2012 at 11:50
  • @Lou just imagine that instead of Class2 we head Interface2. That's the problem I'm facing now. Commented Dec 16, 2018 at 20:52

5 Answers 5

13

For more corrective, implement interface explicitly:

public class Class1<T> : IInterface
where T : Test2
{
    public T Test { get; private set; }

    Test2 IInterface.Test
    {
        get { ... }
    }
}

Then you can avoid compiled error.

Sign up to request clarification or add additional context in comments.

4 Comments

Or indeed return Test instead of throw new NotImplementedException().
@Rawling: it's up to OP, maybe he want to implement in different way
Fair enough. Anyway this does explain why the compiler doesn't support this kind of covariance directly - there's a workaround so the compiler team spent their time doing more important stuff :)
Mr Lippert made the case that every feature, how small, has a big cost. So I accept this answer as I tend to believe the compiler has no other obvious reason to disallow it
5

Since T can be any type derived from Test2, Class1 does not implement IInterface exactly.

More generally, it is not possible to implement an interface by returning a covariant type:

interface IFoo
{
    object Bar { get; }
}

class Broken : IFoo
{
    string Bar { get; } // you cannot expect to implement IFoo this way!
}

2 Comments

"Class1 does not implement IInterface exactly" - well, class1.Test does always return a Test2, right? Similarly broken.Bar always returns an object.
Signature of methods in interface and class is not equal. So class is not implement interface.
4

Change your interface to this and it will compile:

public class Class1<T> : IInterface<T>
    where T : Test2
{
    public T Test { get; private set; }
}

public class Test2
{
}

internal interface IInterface<T>
    where T : Test2
{
    T Test { get; }
}

Comments

1

Is it feasible for you to make your interface generic e.g.

public class Class1<T> : IInterface<T>
    where T : Test2
{ 
    public T Test { get; private set; } 
} 

public class Test2 
{ 
} 

internal interface IInterface<T>
{ 
    T Test { get; } 
} 

Or are you trying to avoid generics on the interface (there are good reasons for that too!)

1 Comment

Yep, was trying to avoid it so I could write generic code where the compiler otherwise would expect a type parameter
1

Interface say that property Test is of Test2 Type. In your implementation Class1 property Test is of some class that inherited of Test2 but not exactly it. To do what you want, you need write something like this:

public class Class1<T> : IInterface
    where T : Test2
{
    private T _test;
    public Test2 Test { get{return _test} }
}

public class Test2
{ 
}

internal interface IInterface 
{
    Test2 Test { get; }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.