为什么C#在完全知道它没有结构类型时会取笑?

时间:2013-04-20 10:16:57

标签: c# interface casting structural-typing explicit-conversion

我很惊讶今天看到这是可能的,但我担心这必须在之前讨论过。

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,技术上很好。

2 个答案:

答案 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是一个类 - 编译将失败