I have two classes:
public class Asset { }
public class Stock : Asset
{
...
}
When I write:
Stock m = new Stock ();
Asset а = m;
Stock s = (Stock) а;
Everything works fine!
But when I write in this way:
Asset а = new Asset();
Stock s = (Stock) а;
result is InvalidCastException, why?
In your first instance, a
is a reference of type Asset
, but it's referring to an object whose actual runtime type is Stock
.
Stock m = new Stock ();
Asset а = m;
Stock s = (Stock) а;
m
, a
, and s
are all different references to the same actual object, whose type is Stock
.
Here, the actual object not a Stock
. It's just an Asset
:
Asset а = new Assert();
Stock s = (Stock) а;
Because a Stock
inherits from Asset
, it is a superset of Asset
. You can pretend a Stock
is an Asset
and that's fine, because Stock
is, in part, an Asset
-- plus whatever else it adds on its own. Naturally, that doesn't cut both ways: An Asset
doesn't have all the stuff Stock
has, so you can't treat it as if it were a Stock
.
Your assignment to a
in the first example didn't change the object into an Asset
, or create a new Asset
and assign it to m
. It was still the same object.
The type of the reference is only part of the story.
Try this:
Stock m = new Stock ();
Asset а = m;
// This will print "Stock" -- it's still that same actual Stock object.
Console.WriteLine(a.GetType());
Stock s = (Stock) а;
Classes are "reference types". They exist on "the heap", out in the darkness somewhere, and you only ever manipulate references to them. Integers and doubles are different. They're "value types":
int n = 4;
double d = (double)n;
That code actually creates a new double, equal to 4.0. d
doesn't "refer to" n; it is its own, different value. That's very different from how reference types work.
This stuff is a fundamental feature of the .NET type system. A struct
(for example DateTime
) is also a value type.