为什么C#完全知道它没有';你没有吗?

为什么C#完全知道它没有';你没有吗?,c#,interface,casting,structural-typing,explicit-conversion,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

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

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
不是
icandad
,从技术上讲。

将类转换为接口是允许的。但例如,如果ICanAdd是一个类,编译将失败

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

如果您查看的第6.2.4节,您将看到,如果您将
MyAdder
类标记为
sealed
,编译器实际上会抱怨,因为这样它将确定不可能进行转换,因为不可能存在派生类型。但只要它不能消除所有的怀疑,它就会允许一个明确的转换。

为什么被否决?我是不是又在进行一次大脑放屁训练?问得好!在
adder.Add
中定义的
adder
在哪里?你是说
我添加了
?@dasblinkenlight是的。我将编辑输入:)但无论如何,该行不会被命中。编译器允许您将
MyAdder
转换为
icandad
,因为它无法证明不存在显式转换。例如,
myAdder
可以是实现
ICanAdd
接口的派生类型的实例,在这种情况下允许强制转换。@nawfal“可能是”部分就是它是显式转换而不是隐式转换的原因。如果它确实知道这是一个有效的转换,您就不需要强制转换,您只需分配。您可以将显式强制转换的需要视为编译器发出的一个信号:“嘿,这可能不起作用。我会尝试一下,但我希望您知道自己在做什么。”我根据您的评论更新了您的答案,这让我明白了这一点。希望一切顺利。