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?
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?
new Dog()
is an expression that creates a newDog
instance. It invokes the parameterless constructor of theDog
class.a
is a variable: a storage cell in memory that holds a reference to theDog
instance after assignment.The difference is that a
Dog
variable can only hold a reference to aDog
instance (or an instance of any class that derives fromDog
), while anobject
variable can hold a reference to anobject
instance (or an instance of any class that derives fromobject
– which theDog
class does).When you have a
Dog
variable, you can invoke any method defined by theDog
class (and its base classes) on the referenced instance. When you have anobject
variable, you can only invoke the methods of theobject
class on the instance.Your first line creates a variable of type
object
.The compiler won't let you treat that as a
Dog
.Both statements involve calling the default constructor of
Dog
as you mention yourself; therefore, it is evident that in both cases aDog
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:
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
Since all reference types implicitly derive from
System.Object
, assigning aDog
to a variable of static typeobject
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 callingGetType
.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 beDog
, you tell the compiler that you do not intend to use that variable for storing anything other than aDog
. 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 usingd
in any way that not every kind ofDog
should support.Consider:
The last line causes a compiler error because it violates the static typing contract: you told the compiler that
o
can be anything deriving fromSystem.Object
, but not all of the things deriving from that have a methodWoof
. So the compiler is trying to protect you by saying "What are you doing there? I cannot prove² that whatever is ino
can woof! What if it were aCat
?".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.
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.
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 typeobject
, a superclass ofDog
; in the second case, you declare a variable of typeDog
. The difference is that in the subsequent code you can invoke methods ofDog
without a cast only when you declare the variable asDog
; if you declare it asobject
, you would need a cast.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 simplyobject
).