views:

97

answers:

3

Sorry about the strange title. I really have no idea how to express it any better...

I get an error on the following snippet. I use the class Dummy everywhere. Doesn't the compiler understand the constraint I've added on DummyImplBase? Is this a compiler bug as it works if I use Dummy directly instead of setting it as a constraint?

Error 1 'ConsoleApplication53.DummyImplBase' does not implement interface member 'ConsoleApplication53.IRequired.RequiredMethod()'. 'ConsoleApplication53.RequiredBase.RequiredMethod()' cannot implement 'ConsoleApplication53.IRequired.RequiredMethod()' because it does not have the matching return type of 'ConsoleApplication53.Dummy'. C:\Documents and Settings\simen\My Documents\Visual Studio 2008\Projects\ConsoleApplication53\ConsoleApplication53\Program.cs 37 27 ConsoleApplication53

public class Dummy
{
}

public interface IRequired<T>
{
    T RequiredMethod();
}

public interface IDummyRequired : IRequired<Dummy>
{
    void OtherMethod();
}

public class RequiredBase<T> : IRequired<T>
{
    public T RequiredMethod()
    {
        return default(T);
    }
}

public abstract class DummyImplBase<T> : RequiredBase<T>, IDummyRequired
    where T: Dummy
{
    public void OtherMethod()
    {
    }
}
A: 

I you change the DummyImplBase to:

public abstract class DummyImplBase<T> : RequiredBase<Dummy>, IDummyRequired
        where T : Dummy
{
    public void OtherMethod()
    {
    }
}
Trond
But if I make RequiredMethod virtual and tries to override it using either T or Dummy, this solution doesn't work.
simendsjo
+1  A: 

You could add this to DummyImplBase:

   public Dummy RequiredMethod() { return base.RequiredMethod(); }

EDIT: Or, if you're using C# 4.0, you could change definition of IRequired like so:

public interface IRequired<out T>

then remove IDummyRequired and you would still be able to assign derived classes to IRequired<Dummy> (but not to IDummyRequired).

2nd EDIT: Your original code did not compile, because T could be Dummy or a class derived from Dummy. And the implemented Method

public DummyDerived RequiredMethod() 

has not the same as signature as

public Dummy RequiredMethod()

which was declared in IDummyDerived.

Henrik
This seems more like a tedious hack by hiding the original methods, and still.. This doesn't give me the advantage of generics. Then I have to do this in the derived classes as well to give the same result.
simendsjo
see my edit, if using C# 4.0 is an option.
Henrik
Using 3.5 still
simendsjo
2nd Edit: Ah, of course. Didn't really think of that as DummyDerived could be used as Dummy, but it all makes sense. Thanks
simendsjo
A: 

If I make IDummyRequired generic too it works, so I guess I'll have to change some of my design to make this possible. I'm still hoping to find out why my solution doesn't work though.

public class Dummy
{
}

public interface IRequired<T>
{
    T RequiredMethod();
}

public interface IDummyRequired<T> : IRequired<T>
    where T : Dummy
{
    void OtherMethod();
}

public class RequiredBase<T> : IRequired<T>
{
    public T RequiredMethod()
    {
        return default(T);
    }
}

public abstract class DummyImplBase<T> : RequiredBase<T>, IDummyRequired<T>
    where T: Dummy
{
    public void OtherMethod()
    {
    }
}
simendsjo
see my 2nd edit as to why your original code didn't compile.
Henrik