用我认为非常简单的一段代码踩了自己的脚。代码比语言更有说服力,所以在这里。
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
}