Do interfaces derive from System.Object? C# spec says yes, Eric says no, reality says no
It's not quite as simple a question as you might think :)
Interfaces don't derive from object
but you can call the members of object
on them. So you can call ToString()
on an expression which has a compile-time type of IDisposable
, for example.
Coincidentally, I overhead a conversation between Neal Gafter and Eric at NDC discussing exactly this point...
I believe section 4.2.2 of the spec is over simplified, unfortunately. Hopefully Mads and Eric will fix it up for a future release - I'll mail them to make sure they see this question.
I'm also struggling to find anything in the spec to back up the rest of this answer. Section 3.4.5 of the C# 4 spec comes as close as I can find:
The members of an interface are the members declared in the interface and in all base interfaces of the interface. The members in class
object
are not, strictly speaking, members of any interface (13.2). However, the members in classobject
are available via member lookup in any interface type (7.4).
The conversion from an interface type to object
is covered by section 6.1.6:
The implicit reference conversions are:
- From any reference-type to
object
anddynamic
.
Jon is (as usual) spot on. It is not as easy as you think!
The spec is vague and slightly contradictory. In this particular case it is probably best to squint a little bit and get the gist of what the spec means to convey rather than narrowly parsing it for precise definitions.
The simple fact of the matter is that "inheritance" is a very overused term in object-oriented programming. (I seem to recall that C++ has six different kinds of inheritance, though I'd be hard pressed to name them all on short notice.)
If I had my druthers then the C# specification would clearly call out a difference between inheritance and interface implementation. Inheritance is *a code-sharing technique for class (and delegate) and struct (and enum) types"; its mechanism is that all heritable members of a base type become members of a derived type. That is in contrast with interface implementation which is a requirement that an implementing type have a certain set of public members. Those two things seem conceptually very different to me; one is about sharing existing members and the other is about requiring certain members.
However, the spec does not do so; it conflates the two under the rubric of inheritance. Given that these two somewhat different things have the same name in the spec, it is hard to reason clearly and precisely about the differences between them.
I personally prefer to think that object is not the "base type" of any interface, and that the members of object are not inherited by the interface. That you can call them on an instance of an interface is more like a courtesy extended to you by the compiler so that you do not have to insert a cast to object in there.
UPDATE: I note for new readers that this answer was written ten years before default interface implementations were added to C#. This new feature does not bear directly upon the question that was asked here. However, it does muddy the waters even more!
Now we are in a situation where implementing classes may "inherit" not just the requirement to provide an implementation of an interface member, but also an implementation of that member. This feels much more like what we would traditionally think of as "inheritance".
Even in this new and slightly more confusing situation, I recommend that we continue to use jargon carefully:
- Inheritance continues to be the property that members of one type are also members of another type.
- It is still the case that any expression of any interface type is convertible to a reference to
object
, which may benull
. - It is still the case that the compiler will allow you to call members of
object
when the receiver is an expression of any interface type.
Interface types do not inherit from Object
, but storage locations of interface types hold references to class-type objects which (if non-null) are guaranteed to inherit from System.Object
.
I think understanding what's going on will be easiest if one starts by examining the difference between value types and class types. Suppose I have a structure:
public struct SimplePoint {public int x,y;}
and I have two methods
public doSomethingWithPoint(SimplePoint pt) ...
public doSomethingWithObject(Object it) ...
and cal each method:
SimplePoint myPoint = ...;
doSomethingWithPoint(myPoint);
dosomethingWithObject(myPoint);
The first call does not pass a thing that derives from Object
. It instead passes the contents of all of SimplePoint
's public and private fields. The second call needs a thing which derives from Object
, so it generates a new heap object instance of type SimplePoint
which contains all the public and private fields of the value-type SimplePoint
, and loads all those fields with the corresponding values from myPoint
, and passes a reference to that object.
Note that the type SimplePoint
actually describes two different kinds of things: a collection of fields (i.e. the value type) and a heap-object type. Which meaning is applicable depends upon the context where the type is used.
Interface types have a similar wrinkle: when used as storage-location types, they specify that the storage location will hold an object reference. When used as a generic constraint, they say nothing about how the type will be stored. Thus, a storage location of an interface type will hold a reference to a heap object that genuinely does inherit from System.Object
, but a variable of a type constrained to an interface might hold either a reference or a bunch of fields.