Not everything derives from object


I hear a lot of myths about C#. Usually the myths have some germ of truth to them, like "value types are always allocated on the stack". If you replace "always" with "sometimes", then the incorrect mythical statement becomes correct.

One I hear quite frequently is "in C# every type derives from object". Not true!

First off, no pointer types derive from object, nor are any of them convertible to object. Unsafe pointer types are explicitly outside of the normal type rules for the language. (If you want to treat a pointer as a value type, convert it to System.IntPtr, and then you can use it as a value type.) We'll leave pointer types aside for the rest of this discussion.

A great many types do derive from object. All value types, including enums and nullable types, derive from object. All class, array and delegate types derive from object.

These are all the "concrete" types; every object instance that you actually encounter in the wild will be either null, or a class, delegate, array, struct, enum or nullable value type. So it would be correct, though tautological, to say that all object instances derive from object. But that wasn't the myth; the myth stated was that all types are derived from object.

Interface types, not being classes, are not derived from object. They are all convertible to object, to be sure, because we know that at runtime the instance will be a concrete type. But interfaces only derive from other interface types, and object is not an interface type.

"Open" type parameter types are also not derived from object. They are, to be sure, types. You can make a field whose type is a type parameter type. And since generic types and methods ultimately are only ever used at runtime when fully "constructed" with "concrete" type arguments, type parameter types are always convertible to object. (This is why you cannot make an IEnumerable<void*> -- we require that the type argument be convertible to object.) Type parameter types are not derived from anything; they have an "effective base class", so that type arguments are constrained to be derived from the effective base class, but they themselves are not "derived" from anything.

The way to correct this myth is to simply replace "derives from" with "is convertible to", and to ignore pointer types: every non-pointer type in C# is convertible to object.

Comments (47)

  1. cpun says:

    "Interface types, not being classes, are not derived from object. They are all convertible to object,.."

    I have a problem with this.

    Interfaces in C# roughly model contracts. That is, I can explicitly state what my class will support via an interface.

    Also consider the following code:

              IContract contract = new A(); //A implements IContract and derives from object

               Object o = contract;// “upcasting”

    And therefore since the conversion in line 2 is legal in C# I am basically stuck with IContract being “forced” to expose the methods from Object like ToString(), GetHashCode() etc. This seems a little paradoxical to me since on the one hand an Interface should be a contract defined by me, but on the other hand the language is forcing me to include methods from System.Object in this contract. What if I do not want ToString() to be called via this interface to prevent serializing my object to a corresponding string? Should there not be a way to explicitly “shut off” these inherited methods specifically for interfaces?

  2. My deskmate here in the office says that he had an COM object instance (implemented in delphi) which was not convertible to Object in C# (which makes sense, given that it does not expose those methods). So it seems that Interface types are not guaranteed to be convertible to object.

  3. Douglas McClean says:

    What about "types" like IDictionary<,>? Granted, that isn’t a type in the language, and there is no value anywhere with that type, but there are instances/is an instance of System.Type that represents it. Another thing to watch out for in some reflection code paths, someone could pass you a "type" like that.

  4. Tom says:

    @cpun:  The interface isn’t inheriting or exposing members of Object.  Object mandates that anything converted to it inherits these members.

    @Markus:  Implementation details are necessary to validate this claim.  I’ll bet there was an implementation error during the conversion process.

    @Douglas:  There is no type Dictionary<,>; you cannot declare an instance of or otherwise make any programmatic use of Dictionary<,>.  There is a type Dictionary<TKey, TValue>, wherein the type parameters are suffused with existing types.  The type parameters themselves act as placeholders for types to be defined by the programmer.

    I’ve known for some time that interfaces were the exception to the "everything is an Object" rule, but I never considered these other cases.  Enlightening.

  5. cpun says:

    @tom That still doesnt address my conceptual problem with why a contract would be forced to have those methods. Whether it be due to conversion or inheritance is an implementation detail.

  6. Tony Cox [MSFT] says:

    @cpun: The *contract* isn’t forced to have anything. An interface (contract) forces a class which implements it to have appropriate methods. When you implement a class, it derives from object, which already has some methods on it. You are certainly not obliged to override them if you don’t want to.

    It sounds like your argument is either that (a) it’s not desirable to force all classes to derive from object, or (b) object should not have any methods. Both are valid questions to consider, but neither is directly related to interfaces.

    While it might seem more "clean" to not have a common base class (object), or else to have a common base class but make it empty, as a practical matter there’s very little downside to these rules and considerable practical benefit.

  7. Banjobeni says:

    …not to forget that Object exposes Methods that would not have a home otherwise and that are core to the language(s), like Equals(object, object) and ReferenceEquals(object, object).

  8. nice, good information, as always

  9. Douglas McClean says:

    @Tom

    I don’t disagree with you that there is no such type. However, there is such a "type," which was the caution I was trying to point out. You’ll find that typeof(IDictionary<,>) is an instance of System.Type with some unusual properties, that’s all I’m trying to say.

  10. Chris says:

    @Tom

    That type does indeed exist. Incomplete generic types are accessible via reflection, and can be very useful in some cases. For example, you can use this to do instantiate generic types whose type parameters are only known at runtime.

  11. cpun says:

    @Tony cox

    I thought my point was clear and yes it is pertinent to mostly interfaces which are meant to describe a class saying "i will provide this service to the world". Because of the convertibility to object the problem now is that they have these methods that are infact forced onto the interface. Reminds me of COM interfaces and the AddRef, Release etc methods which were ugly.

    Not convinced? How is this:

    ICustomer customer = createCustomer();

    customer.GetHashCode();//makes as much sense as having horns on a fish..

  12. zvolkov says:

    Most people don’t use words careful enough, that’s why they say "all types derive from object". What they meant to say is: "all classes inherit from object" — and this is always true, unless you start shifting definitions of "class", "inherits" and "object". But then again, I can come up with a new more precise statement that will still be valid. This does not mean my idea behind the statement was invalid, it just means I need a more precise wording.

  13. David Kean says:

    >"Open" type parameter types are also not derived from object. They are, to be sure, types. You can make a field whose type is a type parameter type.

    Reflection does not agree with you there – Type.BaseType where T is an type parameter without any constraints, returns System.Object.

  14. AC says:

    @zvolkov you’re absolutely correct, but the issue arises because there are the people who understand and use the terms interchangeably, relying on other readers to be like themselves and understand in context of the communication.

    However it’s the people who don’t understand the differences that the clarification is needed, and they run into trouble, or start making 1/2 correct inferences and mis-communicating to others.

    It pays to be precise, and when in the habit of using the correct terminology, comprehension becomes easier for all parties.

  15. Larry Smith says:

    I’m surprised you didn’t mention delegate types in your discussion.

  16. sukru says:

    @cpun:

    ICustomer customer = createCustomer();

    customer.GetHashCode();//makes as much sense as having horns on a fish..

    Makes all the sense if:

    Dictionary<custromer, double> balance = new …;

    In order to use ICustomer (or any other type) you need to have equality and hash code members. There are cases for the other ones, too.

  17. Tim says:

    @cpun:

    It sounds like what you really want is for Object’s methods to be "hidden," most likely at the IDE level.  I actually think it would be great to bump up intellisense’s intelligence and allow you to sort out some of the more obnoxious inherited members.

    At runtime, you may think you don’t want those methods, but as sukru pointed out, you probably do, you just don’t want to have to think about it.

  18. cpun says:

    @sukru

    So you think the fact that someone might want to use object interfaces (or any object for that matter) as a key in a map, puts the onus of providing a hash value on the interface (or class) for that object? So if we invent a new data structure which requires that all objects stored in it have a property (lets call it quantum hash) then all objects should provide GetQuantumHashCode()? How these objects are stored by an external actor in a data structure shouldnt be a reason to change the interface, contract, class or whatever.

  19. cpun says:

    @Tim

    Tool-nuisance and cluttering is definitely one aspect of it. Another is that it just does not make any sense to me, especially for interfaces. My comments above make clear why.

  20. alex says:

    I’m surprised you didn’t mention delegate types in your discussion..

  21. Gilles Michard says:

    what about the "void" type? why is not Func<void> allowed?

  22. Tom says:

    @Chris:  Thanks for the info.  I wasn’t aware we could specify type parameters at run-time.

  23. Tom says:

    @cpun:  If you have this much enmity toward a harmless and potentially very useful feature, you’re using the wrong language.  .NET is designed to simplify things.  This is accomplished in part by providing a variety of "default" methods so the user doesn’t have to recreate them:  Equals(), GetHashCode(), MemberwiseClone().  If you have a problem with this, C++ and STL (or some other combination) is your answer.

  24. James says:

    If interface is not an Object why does this code print it is an object?

    interface ITest

    {

    void Run();

    }

    class Program

    {

    static void Main(string[] args)

    {

    if(typeof(ITest) is Object)

    {

    Console.WriteLine("ITest is an Object.");

    }

    else

    {

    Console.WriteLine("ITest is not an Object.");

    }

    }

    }

  25. Remco says:

    @ James

    because typeof(ITest) returns an instance of System.Type representing the interface ITest, not the  ITest interface itself

  26. carlos says:

    @James: "typeof(ITest) is Object" is true because typeof(ITest) returns the instance of System.Type describing ITest.  And System.Type derives from Object.

  27. cpun says:

    @Tim

    I have no enmity towards .NET/C#. I love the platform and language. But like anything else in this universe, it is not perfect just like its designers. Criticizing aspects of a language does not damn the whole language, just those aspects.

  28. Tony Cox [MSFT] says:

    @cpun

    I agree that you have a valid point. However, no design is perfect, and every design is the result of a tradeoff between competing concerns. In this particular case, I tend to prefer the choice made by the CLR designers to include a minimal set of methods in object, rather than leave that class completely empty. It’s a pragmatic choice rather than a "pure" choice, but I think that’s okay in the context of the problem-space the CLR is aimed at.

    In particular, there isn’t any additional burden placed on application or library developers by the inclusion of these methods in object. You don’t have to provide implementations of GetHashCode() or ToString() if you don’t want to – you can just inherit the implementations from object.

    GetHashCode() allows any object to be used as a key in a Dictionary, which is a very common and useful pattern. It’s very convenient to know that any object can be used this way.

    Similarly, ToString() is quite handy, especially in debugging and diagnosic scenarios. Again, knowing that *any* object supports it very convenient.

    The alternative design would have been to have interfaces (IHashable or whatever) that you’d strongly encourage people to implement. You’d end up having to explicitly implement a lot more stuff every time you made a class. Or else you wouldn’t bother, and then a user of your class would be frustrated that they couldn’t use your class as a hash key.

    I’m not saying the alternate design is necessarily a bad one. I’m just saying it makes different tradeoffs.

  29. cpun says:

    @tony cox

    thanks for taking my comments in the spirit they were intended. I have been writing a library based data access DSL @work and since I use interfaces to model the BNF productions the fact that i get these methods ruining my otherwise nice DSL is ticking me off :). But as you said, everything is a trade-off.

  30. David Nelson says:

    @Tony Cox,

    What you propose was not the only alternative design. A better approach would have been to make GetHashCode and ToString static members of Object. The implementation would first check for the IHashCodeProvider or IStringProvider interfaces; if they are implemented on the type, use them, otherwise use the built-in implementation. Not only would this have been a more "pure" design, but it would allow type consumers to determine whether or not a class provides its own implementation of these methods. This would be consistent with casting to any other interface to determine if a type has particular capabilites, like IComparable or INotifyPropertyChanged. This could be especially significant for ToString; there have been several times when I have wanted to display a string which represents an object, but if the object does not provide its own string implementation, I do NOT want to display the type name, which is the default implementation of ToString. If there were an IStringProvider interface, I could check for the existence of the interface and if its not there, provide my own implementation (such as a blank string).

  31. @cpun

    Kzu have a blog post about how you can hide object memebers in interface based dsl:s here: http://www.clariusconsulting.net/blogs/kzu/archive/2008/03/10/58301.aspx

    As a side note IntelliSense in VB.Net these methods are infact NOT callable on an object of an interface type, you have to upcast to Object to use them.

  32. David W says:

    I think the practical reality of an empty or nearly-empty "object" implementation would have been a wildly fragmented spinoff of innumerable very similar "rollup" classes that tried to ramp up a minimalist set of basic functionality, but all subtely mutually incompatible, or at worst 90% reinventions of very similar wheels. I think the design choice was the practical one, if not the philosophically pure one.

  33. cpun says:

    @Patrik

    Thank you! you are awesome.

  34. @tony cox

    For an object to be "usable" as an hash key, you strictly need to override the Equals() and GetHashCode() methods, as the default ones are semantically "strange" for most use cases, so – in effect – you gain nothing but the danger that you override one and forget the other, and so get an inconsisten behaviour.

    And why this preference to Hashable objects, and not Comparable, so sorting, trees etc. are ruled out?

    @Tom: I’ll investigate this myself.

  35. @Tom: Now, one other of my coworkers told me that the WCF Proxies are interface implementations which cannot be cast to Object.

    I’ll investigate this myself…

  36. leo says:

    Could anyone tell me why ICloneable.Equals(a, b) works?

    Does this imply any relation between interface and Object?

    or there is something behind the scene?

  37. tom says:

    @leo:  That’s a good question.  Apparently the compiler knows that *every* object will inherit these static methods, regardless of type, so it allows Object’s static methods to apply to explicitly declared interfaces in this context.  After all, any class that implements ICloneable will be an Object.  Clearly it’s a rule that applies only to Object, since you can’t declare an interface that inherits from a class (not even Object!).

  38. pminaev says:

    @leo, it works because C# language spec requires it to; 7.3 "Member lookup":

    "A member lookup of a name N with K type parameters in a type T is processed as follows:

    * If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (§10.1.5) for T, along with the set of accessible members named N in Object.

    * Otherwise, the set consists of all accessible (§3.5) members named N in T, including inherited members and the accessible members named N in Object. If T is a constructed type, the set of members is obtained by substituting type arguments as described in §10.3.2. Members that include an override modifier are excluded from the set."

    Note how it specifically calls for looking up members in Object, and at the same time makes a distinction between "inherited members" and "members in Object".

    What is the rationale for this when T is an interface type is a different question, but it is understandable. After all, if you can call instance members of Object on a value of interface type as if they were "inherited" from Object, it would only be logical to extend the same pseudo-inheritance to static members.

  39. v.reshetnikov@gmail.com says:

    Even the authors of C# Language Specification were deceived by this myth. 🙂

    Section 4.2.2 says: “The object class type is the ultimate base class of all other types . Every type in C# directly or indirectly derives from the object class type.”

    Yep. Mads is aware of the error and will correct the spec in the next version. — Eric

    Actually, there are some very special value types (like System.TypedReference) that are not convertible to object.

    Yep. One of these days I’ll do a blog post about those very special types. That will at the very least force me to figure out how they work. 🙂 — Eric
  40. Orhan says:

    http://msdn.microsoft.com/tr-tr/library/ms173156(en-us).aspx  this article says "An interface can itself inherit from multiple interfaces.". so, how about that?

  41. antlypls says:

    Also, this myth is sustained by Jeff Richter’s book "CLR via C#, 2nd ed", there is section called "All types are derived from System.Object" in Chapter 4 "Type Fundamentals" of the book.

  42. STJ says:

    What about the “null type”? (see C# Language Specification §9.4.4.6, §11.2.7)

    We decided during the C# 3 design and specification process that having a special type that only contains one value, null, was a bad idea. It seems plausible, and other language specs also do it this way, but ultimately it adds very little value. The null type is quite unusual in that its the only type that doesn’t have a CLR type object associated with it. It is conceptually easier to simply have some expressions be typeless, and be OK with that, than to invent an ad-hoc type solely for the purpose of being able to say what the type of the null literal expression is. This language should have been removed from the C# 3 spec. — Eric

  43. Rakesh says:

    Any idea why following code does not generate compile time error?

       public interface ITest
       {
           void PrintMessage();
       }
      // Class does not implement ITest interface.
       public class BaseClass
       {
       }

      class Program
       {
           static void Main(string[] args)
           {
               BaseClass bclass = new BaseClass();
               // Why compiler does not generate error here….
               ((ITest)bclass).PrintMessage();
           }
       }

    First off, of course it generates an error at runtime. But why not at compile time?

     Suppose we rewrite your program like this:

              BaseClass bclass = GetSomething();
              ((ITest)bclass).PrintMessage();

    Do you agree that the compiler cannot produce an error here? Since BaseClass is not sealed, there could be a derived class that implements ITest, and an instance of it could be returned by GetSomething.

    The compiler is not smart enough to deduce that bclass is always of type BaseClass and never of a more derived class on the codepath that has the cast operator. We do flow analysis, but only for the purposes of determining reachability and definite assignment, not for analyzing the possible runtime types of variables. We could implement such a system, but it would be a lot of work for a small gain.

    — Eric

  44. Bob Bedell says:

    13.2 "The members of class object are not, strictly speaking, members of any iinterface."

    How about this one?

    interface MyInterface

       {

           bool Equals(object obj);

           int GetHashCode();

           Type GetType();

           string ToString();

       }

       class MyClass : MyInterface

       {

            // MyInterface is implicitly implemented  because MyClass implicitly derives from type object.

      }

    Isn’t it really the case that the members of type object are implicitly members of EVERY interface?

  45. AM says:

    The ability to call System.Object’s members is a C# language implementation decision as opposed to the implementation of a language like VB.Net(@Patrick upcast to access System.Object members).

    Calling ToString() on an instance of an object implementing an interface (Iface) produces IL as such:

    L_000f: callvirt instance string [mscorlib]System.Object::ToString()

    Specifying "string ToString();" on the Interface changes the IL such:

    L_000f: callvirt instance string Iface::ToString()

    So as the author states the interface isn’t inheriting those members from System.Object, it’s the compiler that decides to resolve those members to the System.Object class because its a resonable assumption to make that any type that implements Iface is convertable to an object.

  46. ruju says:

    gr8!! this is what i was searching for. I had a gr8 confusion about interface type.

Skip to main content