Arkiliknam
Arkiliknam

Reputation: 1825

C# interface and generic combination. Want to return <T> instead of its base interface

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?

Upvotes: 8

Views: 2214

Answers (5)

Pieter van Ginkel
Pieter van Ginkel

Reputation: 29632

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; }
    }
}

Upvotes: 12

Peter Rennie
Peter Rennie

Reputation: 21

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; }
    }
} 

Upvotes: 2

Eugen Rieck
Eugen Rieck

Reputation: 65274

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
}

Upvotes: 1

Henk Holterman
Henk Holterman

Reputation: 273219

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.

Upvotes: 4

Maheep
Maheep

Reputation: 5605

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; } 
}

Upvotes: 1

Related Questions