Интерфейс C # и общая комбинация.Хотите вернуть <T>вместо своего базового интерфейса - PullRequest
8 голосов
/ 30 декабря 2011

Я наступил на собственные пальцы с тем, что я считал очень простым фрагментом кода. Код говорит лучше, чем слова, так что вот оно.

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'.
}

Компилятор не позволяет мне сделать это, потому что IResponse требует, чтобы Result был IResult, однако я хочу воспользоваться обобщениями в реализующем классе и строго напечатать результат в T. Это просто невозможно, или я пропустил что-то тривиальное?

Ответы [ 5 ]

11 голосов
/ 30 декабря 2011

Они также должны быть сделаны IResponse универсальными:

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

Если вы хотите сохранить интерфейс IResponse без общего параметра в такте, вы можете пойти еще дальше.Ниже приведены два интерфейса, где класс также прозрачно реализует интерфейс без универсального параметра:

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

И, если вы хотите остаться ближе к своей первоначальной реализации, вы можете удалить IResponse<T>и получите следующее:

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; }
    }
}
4 голосов
/ 30 декабря 2011

Если вы «просто» хотите «воспользоваться дженериками», вам не нужно IResponse.

Интерфейс решает другую проблему, которая не совместима с вашим желанием. Рассмотрим

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

Так что либо сделайте IResponse универсальным, либо удалите его вообще.

2 голосов
/ 30 декабря 2011

Попробуйте это

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 голос
/ 30 декабря 2011
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
}
1 голос
/ 30 декабря 2011

Вы должны сделать IResponse универсальным и изменить тип Result в IResponse, так как параметр типа передается этому интерфейсу.

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

public class Response<T> : IResponse<T>
{
    public T Result { get; set; } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...