界面:
接口IPlay <
T >
{}
类:
class Mp3Player:IPlay <
int >
{}
class OggPlayer:IPlay <
double >
{}
DummyPlayer类:IPlay <
对象>
{}
尝试使用:
1. IPlay <
对象>
播放器=新Mp3Player();
2. IPlay <
int >
player2 = new OggPlayer();
为什么1和2的用法无法投射?
int to object,或int to double。在非一般情况下这是可能的。还有其他方法吗?
答案 0 :(得分:4)
您正在尝试执行无效的强制转换。 Mp3Player不是IPlay&lt; object&gt;,它是IPlay&lt; int&gt;。您的OggPlayer是IPlay&lt; double&gt;,而不是IPlay&lt; int&gt;。你不能施放IPlay&lt; int&gt;到IPlay&lt;对象&gt;或者IPlay&lt; double&gt;到IPlay&lt; int&gt;像那样。它们不是相互继承的,因为它们是通用的,它们是彼此强烈区分的不同类型。
在C#4.0中,这种隐式演员可能,并且我可能会强调,因为它将具有改进的共同/反差。但一般来说,跨越不同类型边界的这种隐式转换是不可能的。
答案 1 :(得分:3)
想象:
interface IPlay<T>
{
T GetSomething();
DoSomething(T value);
}
所以,使用时:
IPlay<object> player = new Mp3Player();
然后GetSomething()
可能是类型安全的,但DoSomething(object value)
怎么样? ...该调用无法保证逻辑将对某个对象起作用,因为该播放器需要整数。
请注意,.NET 4有一种机制来指示接口的方差,因此您可以将接口标记为仅使用T
作为返回值,在这种情况下,至少您的第一个分配将起作用。< / p>
但请注意,无论如何,第二个(IPlay<int> player2
)都不起作用,因为double
和int
之间没有继承关系。能够隐式地转换值与继承不同。
答案 2 :(得分:2)
您要做的事情称为covariance,接口类型的C#4将支持此功能。
答案 3 :(得分:1)
Here is a good talk,他描述了协同/反演在C#4.0中的作用(以及其他内容)。
答案 4 :(得分:0)
有一种常见的误解,即IPlay<T>
会产生一个共同的祖先,即IPlay<object>
。这可能很有价值,但事实并非如此。
您必须自己生成并命名共同的祖先:
interface IPlay {}
interface IPlay<T> : IPlay {}