从类型到未实现的显式强制转换接口编译,但在运行时失败 [duplicate]

Explicit Cast From Type to Not Implemented Interface Compiles but Fails in Runtime [duplicate]

提问人:Brendan Lynn 提问时间:8/9/2023 最后编辑:DaiBrendan Lynn 更新时间:8/9/2023 访问量:42

问:

我有一个类和一个接口,如下所示:

internal class DoStuff
{
    public int X { get; }
    public void Do() => WriteLine(X);
    public DoStuff(int X) => this.X = X;
}

internal interface IDoStuff
{
    void Do();
}

该类不实现接口。因此,不存在隐式转换。但是,Visual Studio 的 Intellisense 表示“确实存在显式转换”。这对我来说是有道理的,因为如果一个接口具有一个类的所有相同方法,那么你就没有理由不能从类转换到接口。从逻辑上讲,我推断,您可以在类型声明中专门实现接口的唯一原因是显式实现。DoStuffIDoStuff

我读了这篇文章,它声称这是不可能的。但是,它是在 2011 年编写的,因此我认为 C# 从那时起就发生了变化。C# 5.0 于 2012 年发布,一年后,我使用的是 C# 11.0。因此,为了验证我的理论,我尝试创建并运行以下 C#(.NET 6 顶级代码):

// Program.cs:

using static System.Console;

DoStuff  d = new(2);
IDoStuff i = (IDoStuff)d;
i.Do();

return;

代码编译良好,但是当我尝试运行它时,它在第三行抛出了一个:InvalidCastException

System.InvalidCastException:无法将类型的对象转换为类型。DoStuffIDoStuff

这没有意义。链接的帖子毕竟还正确吗?

如果是这样,我有三个问题。

  1. 如果强制转换无论如何都不会成功,为什么 C# 编译器不会引发生成错误?
  2. 为什么在 C# 中仍然不支持从具有同名函数的类强制转换为未实现的接口?有什么滞留?
  3. 我依稀记得在某处读到,可以在具有相同元素的不同类之间显式转换。这是真的吗?如果是这样,有什么区别?

如果不是,为什么演员不工作?

以下是完整的组合代码:

https://dotnetfiddle.net/WfAHC4

using static System.Console;

DoStuff @do = new(2);
IDoStuff iDo = (IDoStuff)@do;
WriteLine("a");
iDo.Do();
WriteLine("b");
ReadKey(true);

internal class DoStuff
{
    public int X { get; }
    public void Do() => WriteLine(X);
    public DoStuff(int X) => this.X = X;
}

internal interface IDoStuff
{
    void Do();
}
C# 继承 转换 接口实现

评论

0赞 Panagiotis Kanavos 8/9/2023
This made sense to me,不,这没有意义。仅仅因为一个类型具有与另一个类型具有相同名称或签名的方法,并不意味着它继承或实现该其他类型。或者这些方法以任何方式相关。 没有。这在任何强类型语言中都不受支持。Java 和 C++ 都不允许这样做What's the holdup
0赞 Panagiotis Kanavos 8/9/2023
您发布的代码无法编译,因为缺少。发布实际代码。人们可以复制并尝试编译的东西WriteLine
0赞 Matthew Watson 8/9/2023
@PanagiotisKanavos 注意using static System.Console;
0赞 Panagiotis Kanavos 8/9/2023
@MatthewWatson错误的片段。我确实猜到这涉及

答:

2赞 vatbub 8/9/2023 #1

你的意思叫做鸭子打字,像 Go 这样的语言就用它:如果它像鸭子一样走路,那它一定是鸭子,对吧?但是,C# 不支持此功能。相反,您需要显式实现接口。编译器通过不允许隐式转换来警告您。通过使用显式转换,你基本上是在告诉编译器“闭嘴,我知道我在做什么”,因此,编译器会关闭并信任你。