Difference between object a = new Dog() vs Dog a = new Dog()
Asked Answered
O

6

27
object a = new Dog();

vs

Dog a = new Dog();

In both cases a.GetType() gives Dog. Both invoke same constructor (with same hierarchy).

Then can you please tell me the difference between these two statements?

Offertory answered 19/12, 2011 at 2:51 Comment(5)
The beauty of this I found is that sometimes, a method may need to work with more than a Dog. With the Object a = new Dog() statement, you can use it in a method. Similarily, you can do Object b = new Cat(), and you can use that the same way.Removed
@Ken Why not use an interface then? Like HousePet a = new Dog();. Putting shared methods in HousePet interface or an Animal interface.Deeplaid
This HAS to be a duplicate...Chymotrypsin
@Chymotrypsin - shhhh Wait until the rep has been farmed.Mudskipper
Are you asking "what is the semantic difference?" or "which one should I use when?"Homeomorphism
R
36

Both create a Dog object. Only the second allows you to directly invoke Dog methods or to otherwise treat it like a dog, such as if you need to pass the object to a method as a parameter of type Dog (or something in the Dog hierarchy that is more specific than simply object).

object obj = new Dog(); 
// can only see members declared on object
var type = obj.GetType(); // can do this
Console.WriteLine(obj.ToString()); // also this
obj.Bark(); // Error! Bark is not a member of System.Object

Dog dog = new Dog();
// can do all of the methods declared for Object
dog.Bark(); // can finally use the method defined for Dog
Regelate answered 19/12, 2011 at 2:54 Comment(4)
Thanks.I agree with you. But when I write following code object a = new Dog(); Console.WriteLine(a.GetType()); I get an out as Dog and not Object. Why it is that?Offertory
@Omkarpanhalkar, it's getting the type of the instance, not of the variable. This is a runtime mechanism that gets the metadata associated with the instance, and the runtime knows that the instance is a Dog. What you have lost are the compile-time benefits.Regelate
Next time when I was asked something similar, I'll use "treat it like a xxx", which is the most appropriate word, for me as a non English native speaker.Lotte
@Omkarpanhalkar: This answer makes me realized that the ability to express is really important and is part of one's overall quality. I used to answer similar questions(not only in English but also in my mother language), but I always express badly, even I know how everything works.Lotte
C
6

new Dog() is an expression that creates a new Dog instance. It invokes the parameterless constructor of the Dog class.

a is a variable: a storage cell in memory that holds a reference to the Dog instance after assignment.

The difference is that a Dog variable can only hold a reference to a Dog instance (or an instance of any class that derives from Dog), while an object variable can hold a reference to an object instance (or an instance of any class that derives from object – which the Dog class does).

When you have a Dog variable, you can invoke any method defined by the Dog class (and its base classes) on the referenced instance. When you have an object variable, you can only invoke the methods of the object class on the instance.

Cale answered 19/12, 2011 at 2:57 Comment(2)
Thanks.I agree with you. But when I write following code object a = new Dog(); Console.WriteLine(a.GetType()); I get an out as Dog and not Object. Why it is that?Offertory
Because you invoke the GetType method on the Dog instance referenced by a. GetType returns the type of the instance, not of the variable.Cale
G
5

Your first line creates a variable of type object.

The compiler won't let you treat that as a Dog.

Galsworthy answered 19/12, 2011 at 2:54 Comment(2)
unless you cast it, e.g. (Dog)aWichman
@PeterOlson In which case it is no longer a plain objectCarbone
S
5

Both statements contain a declaration and a constructor invocation. The invocations of the constructor are identical, therefore you get a Dog in both cases. The declarations are different: in the first case, you declare a variable of type object, a superclass of Dog; in the second case, you declare a variable of type Dog. The difference is that in the subsequent code you can invoke methods of Dog without a cast only when you declare the variable as Dog; if you declare it as object, you would need a cast.

Selfcongratulation answered 19/12, 2011 at 2:59 Comment(0)
M
4

Both statements involve calling the default constructor of Dog as you mention yourself; therefore, it is evident that in both cases a Dog instance is constructed. This means that both statements end up initializing a variable with an identical instance (this is the part of the statement after the equals).

However, the statements also have another part: the declaration of a variable (this is the part of the statement before the equals). In statically typed languages such as C#, every variable -- more generally, any expression -- has a static type:

object a = new Dog(); // static type: object / runtime type: Dog
Dog b = new Dog();    // static type: Dog / runtime type: Dog

The compiler will not allow you to assign a value to a variable that it cannot prove is of the variable's static type, e.g. it would not allow

Cat c = new Dog(); // unless Dog derives from Cat, which we know isn't true

Since all reference types implicitly derive from System.Object, assigning a Dog to a variable of static type object is OK. You can think of "static type" as what the object is "declared as". You can always determine the static type of something just by reading the source code; this is how the compiler does it.

Then there's also the runtime type of each variable (expression), which I mentioned above. This is the same in both cases, because after all in both cases we have created a Dog. You can think of "runtime type" as what the object actually is. The runtime type of something cannot be determined just by reading the source; you only determine it while you program is running, hence the name. In C#, this is done by calling GetType.

It should be obvious that the runtime type is something that you cannot do without¹; everything has to "be" something after all. But why bother with inventing the notion of static type?

You can think of static types as a contract between you (the programmer) and the compiler. By declaring the static type of b to be Dog, you tell the compiler that you do not intend to use that variable for storing anything other than a Dog. The compiler, in return, promises to not let you violate your stated purpose and produces an error if you attempt to do that. It also prevents you from using d in any way that not every kind of Dog should support.

Consider:

class Dog {
    public void Woof();
}

Dog d = new Dog();
d.Woof(); // OK

object o = new Dog();
o.Woof(); // COMPILER ERROR

The last line causes a compiler error because it violates the static typing contract: you told the compiler that o can be anything deriving from System.Object, but not all of the things deriving from that have a method Woof. So the compiler is trying to protect you by saying "What are you doing there? I cannot prove² that whatever is in o can woof! What if it were a Cat?".

Notes:

¹ This does not mean that every object magically knows what it "is" in all languages. In some cases (e.g. in C++) this information might be used when creating an object, but is then "forgotten" in order to allow the compiler more freedom to optimize the code. If this happens the object still is something, but you cannot poke it and ask it "what are you?".

² Actually, in this trivial example it can prove that. But it won't choose to use this knowledge because honoring the contract of the static type is the whole point.

Marshall answered 19/12, 2011 at 14:53 Comment(3)
Nice answer! This is a good explanation. I just have a couple of small quibbles. First, you say: "It should be obvious that the runtime type is something that you cannot do without" -- and yet there are statically typed languages without any support for tracking runtime types. (For example, runtime type information, RTTI, is optional in C++.) For this to work, the compiler needs to blindly trust the programmer's use of casts: if you say this object here is actually a Dog, then it better well be a Dog at runtime, or Very Bad Things (undefined behavior) will happen. But it does work.Retract
Secondly, it might help if when explaining that GetType() returns the runtime type, you gave a brief explanation about virtual method dispatch. (Off the top of my head, I'm not sure that GetType() actually is a virtual call, but it's a useful jumping-off point to explain the concept.) The whole reason why subtype polymorphism works is because of virtual methods -- that is, because method calls can be dispatched based on the runtime type, not the static type. In fact, you can have polymorphism without static types: just look at Python or Ruby.Retract
@DanielPryden: Regarding the runtime type, I rephrased the passage so that it's clear that the object still is something (e.g. it might have a vtable which decides what exactly), but you cannot ask it to get this information back. Regarding polymorphism your point is totally correct; that was simply a bad last minute thought on my part, which I 've been wanting to remove for the last few hours I 've been AFK.Marshall
K
2

This is useful when you want to use polymorphism and you can use the abstract method that has implementation in Dog. Therefore, in this way object is Dog, even so is Object. So you may use this manner when you want to use polymorphism.

Knotty answered 6/1, 2012 at 9:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.