我很惊讶今天看到这是可能的,但我担心这必须在之前讨论过。
public interface ICanAdd
{
int Add(int x, int y);
}
// Note that MyAdder does NOT implement ICanAdd,
// but it does define an Add method like the one in ICanAdd:
public class MyAdder
{
public int Add(int x, int y)
{
return x + y;
}
}
public class Program
{
void Main()
{
var myAdder = new MyAdder();
var iCanAdd = (ICanAdd)myAdder; //compiles, but for what sake?
int sum = iCanAdd.Add(2, 2); //na, not game for it, cast had already failed
}
}
编译器(正确地?)告诉我在上面的情况中存在显式转换。我很高兴在那里感觉到结构类型,但没有运行时间失败。那么C#什么时候有用呢?任何场景这样的投射会起作用?不管是什么,我确信编译器事先知道myAdder
不是ICanAdd
,技术上很好。
答案 0 :(得分:9)
C#允许从类到接口的显式转换(即使该类没有实现该接口),因为对于所有编译器都知道,实际上可能引用某种类型(不确定性是为什么它是显式的)而不是隐式转换)是 实现接口的派生类型的实例。扩展您的示例,假设您有:
public class DerivedAdder : MyAdder, ICanAdd
{
int ICanAdd.Add(int x, int y)
{
return base.Add(x, y);
}
}
...
MyAdder myAdder = new DerivedAdder();
var iCanAdd = (ICanAdd)myAdder; // Valid in this case
int sum = iCanAdd.Add(2, 2); // sum = 4
如果您查看C# Specification的第6.2.4节,您会看到如果您将MyAdder
类标记为sealed
,编译器实际上会抱怨,因为它会确定无法进行转换,因为不存在任何派生类型。但只要它不能消除每一丝疑问,它都会允许明确的转换。
答案 1 :(得分:1)
C# language specification允许将类转换为接口。但是,例如,如果ICanAdd是一个类 - 编译将失败