C# 接口和泛型组合。想要返回<T>而不是其基本界面



用我认为非常简单的一段代码踩了自己的脚。代码比语言更有说服力,所以在这里。

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要求结果为IResult,但是我想利用实现类中的泛型并将结果强类型为t。这是不可能的,还是我错过了一些微不足道的东西?

他们也必须使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; }
    }
}

如果您"只是"想"利用泛型",则不需要IResponse

接口正在解决另一个问题,一个与您的愿望不兼容的问题。考虑

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

所以要么让IResponse也通用,要么完全删除它。

试试这个

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

应该将IResponse设置为泛型,并将IResponse中Result的类型更改为传递给该接口的类型参数

public interface IResponse<T> where T : IResult
{
    T Result { get; set; }
}
public class Response<T> : IResponse<T>
{
    public T Result { get; set; } 
}
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
}

最新更新