8

Have stepped on my own toes with what I thought was a very simple piece of code. Code speaks better than words, so here it is.

public interface IResponse
{
    IResult Result { get; set; }
}

public class Response<T> : IResponse
    where T : IResult
{
    public T Result { get; set; } 
    // COMPILER ERROR: Property 'Result' cannot be implemented property from interface 'IResponse'. Type should be 'IResult'.
}

The compiler does not allow me to do this because IResponse requires Result to be IResult, however I want to take advantage of generics in the implementing class and strongly type the result to T. Is this just not possible, or have I missed something trivial?

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
Arkiliknam
  • 1,805
  • 1
  • 19
  • 35

5 Answers5

12

They you have to make IResponse generic too:

public interface IResponse<T>
    where T : IResult
{
    T Result { get; set; }
}

public class Response<T> : IResponse<T>
    where T : IResult
{
    public T Result { get; set; } 
}

If you want to keep the IResponse interface without the generic parameter in tact, you can go even fancier. The below has the two interfaces, where the class transparently also implements the interface without the generic parameter:

public interface IResponse
{
    IResult Result { get; set; }
}

public interface IResponse<T> : IResponse
    where T : IResult
{
    T Result { get; set; }
}

public class Response<T> : IResponse<T>
    where T : IResult
{
    public T Result { get; set; } 

    IResult IResponse.Result
    {
        get { return Result; }
        set { Result = (T)value; }
    }
}

And, if you want to stay closer to your original implementation, you can strip out the IResponse<T> and get the following:

public interface IResponse
{
    IResult Result { get; set; }
}

public class Response<T> : IResponse
    where T : IResult
{
    public T Result { get; set; } 

    IResult IResponse.Result
    {
        get { return Result; }
        set { Result = (T)value; }
    }
}
Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
4

If you 'just' want to "take advantage of generics" you don't need IResponse.

The interface is solving another problem, one that is not compatible with your wish. Consider

IResponse r = x ? new Response<int>() : new Response<string>();
r.Result = ... // what type?

So either make IResponse generic too or remove it altogether.

H H
  • 263,252
  • 30
  • 330
  • 514
2

Try this

public class Response<T> : IResponse
    where T : IResult
{
    public T Result { get; set; }
    // COMPILER ERROR: Property 'Result' cannot be implemented property from interface 'IResponse'. Type should be 'IResult'. 

    IResult IResponse.Result
    {
        get { return this.Result; }
        set { this.Result = (T)value; }
    }
} 
1

You should make IResponse generic and change type of Result in IResponse as type paramter passed to this interface.

public interface IResponse<T> where T : IResult
{
    T Result { get; set; }
}

public class Response<T> : IResponse<T>
{
    public T Result { get; set; } 
}
Maheep
  • 5,539
  • 3
  • 28
  • 47
1
public interface IResponse<T> where T : IResult
{
    T Result { get; set; }
}

public class Response<T> : IResponse<T> where T : IResult
{
    public T Result { get; set; } 
    // NO MORE COMPILER ERROR
}
Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92