接口派生自System.Object吗?C#规范说是的,Eric说不,现实说没有

And*_*rey 32 .net c#

问题很简单,在标题中提出.

C#4.0规范说:(§4.2.2)

对象类类型是所有其他类型的最终基类.C#中的每个类型都直接或间接地从对象类类型派生.

Eric Lippert说:

接口类型(不是类)不是从对象派生的.

现实说:

Type t = typeof(ICloneable).BaseType;
Console.WriteLine(t == null);
Run Code Online (Sandbox Code Playgroud)

真正

那么规格错误还是什么?谁相信?

Jon*_*eet 33

问题并不像你想象的那么简单:)

接口不是从中派生出来的,object但您可以调用object它们的成员.因此,您可以调用ToString()具有编译时类型的表达式IDisposable.

巧合的是,我在NDC的Neal Gafter和Eric之间进行了一次谈话,正好讨论了这一点......

不幸的是,我认为规范的第4.2.2节过于简化了.希望Mads和Eric能够为将来的版本修复它 - 我会邮寄它们以确保他们看到这个问题.

我也在努力寻找规范中的任何内容来支持这个答案的其余部分.C#4规范的第3.4.5节尽可能接近我的发现:

接口的成员是在接口和接口的所有基接口中声明的成员.object严格来说,课堂上的成员不是任何界面的成员(13.2).但是,类object中的成员可通过任何接口类型(7.4)中的成员查找获得.

从接口类型转换到object6.1.6节:

隐式引用转换是:

  • 从任何引用类型objectdynamic.

  • 请注意,C# 还允许您通过接口标识符从 `object` 调用 **`static`** 方法。所以不仅是`IDisposable instance = ...; instance.ToString()` 允许,就像你提到的。**`IDisposable.ReferenceEquals(new object(), new object())`** 也是合法的。它调用 `object` 的 `static` 成员。当然,接口不能声明自己的“静态”成员。补充:对于类型参数,C# 不允许通过类型参数名称调用 `static` 成员,因此如果 `T` 是类型参数,则例如 `T.ReferenceEquals(...)` 将不会编译。限制“T”没有帮助。 (2认同)

Eri*_*ert 29

乔恩(像往常一样)现场.它并不像你想象的那么容易!

规范含糊不清,略有矛盾.在这种特殊情况下,最好稍微眯一下并获得规范意味着传达的要点,而不是狭隘地解析它以获得精确的定义.

事实的简单事实是"继承"在面向对象编程中是一个非常过度使用的术语.(我似乎记得C++有六种不同的继承,但我很难在短时间内将它们全部命名.)

如果我有我的druthers,那么C#规范将明确地说明继承接口实现之间的区别.继承是*类(和代表)和struct(和枚举)类型"代码共享技术;其作用机理是,碱类型的所有遗传成员成为派生类型的成员即与对比度.接口的实现要求实施类型具有一定的公共成员.这两件事在概念上对我来说非常不同;一个是关于共享现有成员,另一个是要求某些成员.

但是,规范没有这样做; 它将这两者混合在继承的标题之下.鉴于这两个有些不同的东西在规范中具有相同的名称,很难清楚而准确地推断它们之间的差异.

我个人更喜欢认为该对象不是任何接口的"基类型",并且对象的成员不是由接口继承的.你可以在一个接口实例上调用它们更像是编译器向你扩展的礼貌,这样你就不必在那里插入一个强制转换器.

  • @DeadMG:C++有公共,私有和保护继承,其中C#不 - C#只对类公有继承.C++具有"虚拟继承",C#没有.C++有多重继承,C#没有. (7认同)