473,387 Members | 1,423 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Up casting (base to derived) in C#

Hey All,

I have a C# question for you regarding up casting (base to derived).

I was wondering about the most elegant way (readable, less code) to
cast from a base type to its derived type. Please consider the
following two classes:

class Base {
private int m_valA;
private int m_valB;

public Base() { }

public Base(int a, int b){
m_valA = a;
m_valB = b;
}

public int ValA
{
get { return m_valA; }
set { m_valA = value; }
}

public int ValB
{
get { return m_valB; }
set { m_valB = value; }
}
}//end class

class Derived : Base
{
public int ValAPlusValB
{
get { return base.ValA + base.ValB; }
}
}//end class

Now consider the scenario where I have an instance of Base (someBase)
and could like to up cast it to a Derived instance (someDerived).

Jul 26 '06 #1
24 39111

AtariPete wrote:
Hey All,

I have a C# question for you regarding up casting (base to derived).

I was wondering about the most elegant way (readable, less code) to
cast from a base type to its derived type. Please consider the
following two classes:

class Base {
private int m_valA;
private int m_valB;

public Base() { }

public Base(int a, int b){
m_valA = a;
m_valB = b;
}

public int ValA
{
get { return m_valA; }
set { m_valA = value; }
}

public int ValB
{
get { return m_valB; }
set { m_valB = value; }
}
}//end class

class Derived : Base
{
public int ValAPlusValB
{
get { return base.ValA + base.ValB; }
}
}//end class

Now consider the scenario where I have an instance of Base (someBase)
and could like to up cast it to a Derived instance (someDerived).
I don't understand what you want to know. You cannot cast an instance
to another instance. You cast references, not instances. If you have a
Base reference pointing to an instance of Derived, and you want to cast
it to a Derived reference, there are two ways to do this. Either

Base someBase = new Derived();
Derived someDerived = (Derived)someBase;

or

Base someBase = new Derived();
Derived someDerived = someBase as Derived;

The first way throws an exception if the instance to which "someBase"
refers is not of type Derived or some child type of Derived. The second
way does not throw an exception in this case but instead returns null.

Which one you use depends upon whether, in your application at that
point in the code, the instance must "certainly" be a Derived instance,
or instead the instance "could be" a Derived instance and you want to
handle the case where it isn't.

Is this what you wanted to know?

Jul 26 '06 #2
AtariPete wrote:
Hey All,

I have a C# question for you regarding up casting (base to derived).

I was wondering about the most elegant way (readable, less code) to
cast from a base type to its derived type.
[...]
Now consider the scenario where I have an instance of Base (someBase)
and could like to up cast it to a Derived instance (someDerived).
I personally like this:

Derived someDerived = someBase as Derived;
Jul 26 '06 #3
You cannot cast an instance to another instance.

Bruce,

Thanks for your feedback.

You're correct, I didn't mean "cast one instance to another instance".
I had meant cast an instance of Base to type derived.
Base someBase = new Derived();
Derived someDerived = someBase as Derived;
The issue with this is that i do not control how Base is created. Thus
base is instantiated as follows:
Base someBase = new Base ();
but then if I do the cast
Derived someDerived = someBase as Derived;
someDerived will be null.

Bruce Wood wrote:
AtariPete wrote:
Hey All,

I have a C# question for you regarding up casting (base to derived).

I was wondering about the most elegant way (readable, less code) to
cast from a base type to its derived type. Please consider the
following two classes:

class Base {
private int m_valA;
private int m_valB;

public Base() { }

public Base(int a, int b){
m_valA = a;
m_valB = b;
}

public int ValA
{
get { return m_valA; }
set { m_valA = value; }
}

public int ValB
{
get { return m_valB; }
set { m_valB = value; }
}
}//end class

class Derived : Base
{
public int ValAPlusValB
{
get { return base.ValA + base.ValB; }
}
}//end class

Now consider the scenario where I have an instance of Base (someBase)
and could like to up cast it to a Derived instance (someDerived).

I don't understand what you want to know. You cannot cast an instance
to another instance. You cast references, not instances. If you have a
Base reference pointing to an instance of Derived, and you want to cast
it to a Derived reference, there are two ways to do this. Either

Base someBase = new Derived();
Derived someDerived = (Derived)someBase;

or

Base someBase = new Derived();
Derived someDerived = someBase as Derived;

The first way throws an exception if the instance to which "someBase"
refers is not of type Derived or some child type of Derived. The second
way does not throw an exception in this case but instead returns null.

Which one you use depends upon whether, in your application at that
point in the code, the instance must "certainly" be a Derived instance,
or instead the instance "could be" a Derived instance and you want to
handle the case where it isn't.

Is this what you wanted to know?
Jul 26 '06 #4
"Sericinus hunter" <se*****@flash.netwrote in message
news:er**************@TK2MSFTNGP06.phx.gbl...
I personally like this:

Derived someDerived = someBase as Derived;
I think "as" is frequently misused. In this example, where is the code that
handles when the conversion fails? And if the conversion isn't expected to
fail, why not just use a cast, which will not silently fail if something
goes wrong, but will throw an exception?

///ark
Jul 26 '06 #5

Mark Wilden wrote:
"Sericinus hunter" <se*****@flash.netwrote in message
news:er**************@TK2MSFTNGP06.phx.gbl...
I personally like this:

Derived someDerived = someBase as Derived;

I think "as" is frequently misused. In this example, where is the code that
handles when the conversion fails? And if the conversion isn't expected to
fail, why not just use a cast, which will not silently fail if something
goes wrong, but will throw an exception?
Obviously, there's no error-handling code in a one-line sample. :-)

I usually use "as" if I want to treat the "cast failed" case the same
as I would treat a "null value" case. Often it's not a case of an
error, just a case of how you define your methods. You can always
simply state that passing the "wrong" type of instance results in
such-and-so result, rather than throwing an exception.

"Error" is in the eye of the beholder.

Jul 26 '06 #6

AtariPete wrote:
You cannot cast an instance to another instance.

Bruce,

Thanks for your feedback.

You're correct, I didn't mean "cast one instance to another instance".
I had meant cast an instance of Base to type derived.
Base someBase = new Derived();
Derived someDerived = someBase as Derived;

The issue with this is that i do not control how Base is created. Thus
base is instantiated as follows:
Base someBase = new Base ();
but then if I do the cast
Derived someDerived = someBase as Derived;
someDerived will be null.
Yes. Given your sample code, someDerived will always be null. If the
CLR allowed any other result then it would break type safety. This

Derived someDerived = new Base();

is always illegal and must always fail, or the whole type safety thing
falls apart.

Jul 26 '06 #7
Mark Wilden wrote:
"Sericinus hunter" <se*****@flash.netwrote in message
news:er**************@TK2MSFTNGP06.phx.gbl...
> I personally like this:

Derived someDerived = someBase as Derived;

I think "as" is frequently misused. In this example, where is the code that
handles when the conversion fails? And if the conversion isn't expected to
fail, why not just use a cast, which will not silently fail if something
goes wrong, but will throw an exception?
The code that handles the conversion failure is on the next line. :)
Jul 26 '06 #8
"Bruce Wood" <br*******@canada.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
Obviously, there's no error-handling code in a one-line sample. :-)
My point was that that code is usually all there is. People often don't seem
to realize that "as" -requires- error-handling code, whereas casts don't.
I usually use "as" if I want to treat the "cast failed" case the same
as I would treat a "null value" case.
I'm trying to think of why on earth anyone would want to treat them the
same, but I can't.
Often it's not a case of an
error, just a case of how you define your methods. You can always
simply state that passing the "wrong" type of instance results in
such-and-so result, rather than throwing an exception.
And that is way over my head.

///ark
Jul 26 '06 #9
Mark Wilden wrote:
"Bruce Wood" <br*******@canada.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
Obviously, there's no error-handling code in a one-line sample. :-)

My point was that that code is usually all there is. People often don't seem
to realize that "as" -requires- error-handling code, whereas casts don't.
I usually use "as" if I want to treat the "cast failed" case the same
as I would treat a "null value" case.

I'm trying to think of why on earth anyone would want to treat them the
same, but I can't.
Here's an example, both of this and of what I was talking about after
that:

public override bool Equals(Object obj)
{
MyType other = obj as MyType;
return other != null && other._id == this._id;
}

If I pass some other type to Equals, should it throw an
ArgumentException, or return false? If I pass null to Equals, should it
throw an ArgumentNullException, or return false? It all depends upon
your definition of what "Equals" means, and how you want to treat edge
cases. You may choose to make Equals very cranky and have it throw
exceptions, or simply say, "No... that is not equal to this."

Jul 26 '06 #10
"Bruce Wood" <br*******@canada.comwrote in message
news:11*********************@b28g2000cwb.googlegro ups.com...
public override bool Equals(Object obj)
{
MyType other = obj as MyType;
return other != null && other._id == this._id;
}
I see what you mean - that makes sense.

///ark
Jul 26 '06 #11
Bruce Wood <br*******@canada.comwrote:
Here's an example, both of this and of what I was talking about after
that:

public override bool Equals(Object obj)
{
MyType other = obj as MyType;
return other != null && other._id == this._id;
}

If I pass some other type to Equals, should it throw an
ArgumentException, or return false? If I pass null to Equals, should it
throw an ArgumentNullException, or return false? It all depends upon
your definition of what "Equals" means, and how you want to treat edge
cases. You may choose to make Equals very cranky and have it throw
exceptions, or simply say, "No... that is not equal to this."
In this case it's actually less of an open queston than it might be -
the MSDN documentation states that it should return false. I see your
point though, and in other situations where the documentation is less
clear, it's a much more difficult decision.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 26 '06 #12

Jon wrote:
Bruce Wood <br*******@canada.comwrote:
Here's an example, both of this and of what I was talking about after
that:

public override bool Equals(Object obj)
{
MyType other = obj as MyType;
return other != null && other._id == this._id;
}

If I pass some other type to Equals, should it throw an
ArgumentException, or return false? If I pass null to Equals, should it
throw an ArgumentNullException, or return false? It all depends upon
your definition of what "Equals" means, and how you want to treat edge
cases. You may choose to make Equals very cranky and have it throw
exceptions, or simply say, "No... that is not equal to this."

In this case it's actually less of an open queston than it might be -
the MSDN documentation states that it should return false. I see your
point though, and in other situations where the documentation is less
clear, it's a much more difficult decision.
For my money, this is one of the things that makes error handling such
a bear. If you make your methods very strict and cranky, so that they
throw an exception for the slightest offense, you end up with client
code having to do lots of checking before passing arguments to this
cranky method.

If, on the other hand, you let things like wrong types or nulls slide
by returning some sort of default value, you run the risk, as Mark
pointed out, of having errors go undetected.

Often when you're writing a method you don't know enough about how it
will be used to know whether a given situation should be considered an
error or not. Making the wrong decision can cause problems down the
road... not intractable problems, but annoying ones.

Jul 26 '06 #13
so where does this leave us. how might I up cast then the base class
isn't instantiated with the derived type?

Jul 27 '06 #14
AtariPete <pc******@gmail.comwrote:
so where does this leave us. how might I up cast then the base class
isn't instantiated with the derived type?
Firstly, just to correct your terminology, I believe you're actually
talking about *down*casting. Upcasting is the (almost always
unnecessary) casting from the derived class to the base class.

Now, as for downcasting when the instance in question *isn't* an
instance of the derived class - you can't. The cast won't work (which
is a good thing really - otherwise you'd have to "guess" what the
values of extra fields would be, for starters). What you *could* do is
write a constructor in the derived class which takes a reference to an
instance of the base class, and creates a new instance of the derived
class with mostly the same field values, etc.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 27 '06 #15
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Upcasting is the (almost always
unnecessary) casting from the derived class to the base class.
How "almost"? (I have the unpleasant feeling that I'm about to learn
something.)

///ark
Jul 27 '06 #16
Mark Wilden <Ma********@newsgroups.nospamwrote:
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Upcasting is the (almost always
unnecessary) casting from the derived class to the base class.

How "almost"? (I have the unpleasant feeling that I'm about to learn
something.)
You sometimes need to cast in order to pick the right overload. For
instance:

using System;

class Test
{
static void Main()
{
string x = "hello";
Foo(x);
Foo((object)x);
}

static void Foo(string x)
{
Console.WriteLine ("Foo(string)");
}

static void Foo(object o)
{
Console.WriteLine ("Foo(object)");
}
}

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 27 '06 #17
Mark Wilden wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
>Upcasting is the (almost always
unnecessary) casting from the derived class to the base class.

How "almost"? (I have the unpleasant feeling that I'm about to learn
something.)
To my understanding, using this construct
((BaseClass)instanceOfDerivedClass).Method() you will call base class
implementation of Method(), given it is not virtual and overridden
in the derived class.
Jul 27 '06 #18
Dont forget that you can also use the is keyword:

if (obj is MyType)
{
MyType myObject = (MyType)obj;
// do my thing
}

I also believe casting can return null (if supplied with null) so error
checking is also needed if you cast (except above where you pre-check
its safe)

Tony

Jul 28 '06 #19
Hello Tigger,

Almost always the better pattern is to try the cast with the "as" operator:

MyType myObject = obj as MyType;
if (myObject != null)
{
// do my thing
}

This is more efficient (and in my opinion is more direct to read).

Thanks,
Shawn Wildermuth
Speaker, Author and C# MVP
http://adoguy.com
Dont forget that you can also use the is keyword:

if (obj is MyType)
{
MyType myObject = (MyType)obj;
// do my thing
}
I also believe casting can return null (if supplied with null) so
error checking is also needed if you cast (except above where you
pre-check its safe)

Tony

Jul 28 '06 #20
Hi Shawn,

I would have thought the "is" would be more efficient than the "as"
plus null check?

I guess if normal flow is for it to pass the null check then the
argument is if an "is" plus cast is slower than an "as" plus null
check. Which I would guess to be the case. So in those scenarios it
would be faster to do it your way.

I tend to use the pattern as a kind of switch statement

if (obj is AType)
{
AType aType = (AType)obj;
// do atype special things
}
else if (obj is BType)
{
BType bType = (BType)obj;
// do btype things
}

With this scenario its not the most readable but in my opinion it is
slightly easier to read than using "as"s and null checks.

Of course I try to avoid doing this sort of thing by using interfaces,
inheritance, strong typing, generics etc.

Tigger

Shawn Wildermuth (C# MVP) wrote:
Hello Tigger,

Almost always the better pattern is to try the cast with the "as" operator:

MyType myObject = obj as MyType;
if (myObject != null)
{
// do my thing
}

This is more efficient (and in my opinion is more direct to read).

Thanks,
Shawn Wildermuth
Speaker, Author and C# MVP
http://adoguy.com
Dont forget that you can also use the is keyword:

if (obj is MyType)
{
MyType myObject = (MyType)obj;
// do my thing
}
I also believe casting can return null (if supplied with null) so
error checking is also needed if you cast (except above where you
pre-check its safe)

Tony
Jul 28 '06 #21
Tigger <to**@grunt.tvwrote:
I would have thought the "is" would be more efficient than the "as"
plus null check?
No. "is", "as" and a cast all do pretty much the same thing, and that
thing is more expensive than a null check. Therefore is+cast is more
expensive than as+null check.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 28 '06 #22
Which is what I said later.

However an "is" is more efficient than an as+null check so if the ratio
of matches is low it is better to use "is"s and if the ratio is high
use as+null checks

If you are doing multiple checks like my example its most likely the
list of "is"s plus a single cast (when matched) will be more efficient
than a list of as+null checks.

Theres probably a break even point, say 5 ;-)

Tigger
Jon wrote:
Tigger <to**@grunt.tvwrote:
I would have thought the "is" would be more efficient than the "as"
plus null check?

No. "is", "as" and a cast all do pretty much the same thing, and that
thing is more expensive than a null check. Therefore is+cast is more
expensive than as+null check.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 28 '06 #23
Tigger <to**@grunt.tvwrote:
Which is what I said later.

However an "is" is more efficient than an as+null check so if the ratio
of matches is low it is better to use "is"s and if the ratio is high
use as+null checks

If you are doing multiple checks like my example its most likely the
list of "is"s plus a single cast (when matched) will be more efficient
than a list of as+null checks.
"is" *is* an as+null check, in fact. In IL, "is" compiles to:
IL_0007: ldloc.0
IL_0008: isinst [mscorlib]System.String
IL_000d: ldnull
IL_000e: cgt.un
IL_0010: ldc.i4.0
IL_0011: ceq
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: brtrue.s IL_0024

"as Stream != null" compiles to:
IL_0024: ldloc.0
IL_0025: isinst [mscorlib]System.IO.Stream
IL_002a: ldnull
IL_002b: ceq
IL_002d: stloc.1
IL_002e: ldloc.1
IL_002f: brtrue.s IL_003e

I'm not sure what there's the additional cgt.un in the "is" case, but I
doubt that it gets as far as the generated native code...
Theres probably a break even point, say 5 ;-)
Is it fair to assume that you pulled that number out of thin air?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 28 '06 #24
Ah,

So if "is" is equivalent to an as+null check then it would be best to
do as+null checks and skip the need for a cast.

I was working on "is" being equal to an "as" as you stated in an
earlier post.

I stand corrected.

5 seemed a good random number, I did indicate that though.

Tigger

Jon wrote:
Tigger <to**@grunt.tvwrote:
Which is what I said later.

However an "is" is more efficient than an as+null check so if the ratio
of matches is low it is better to use "is"s and if the ratio is high
use as+null checks

If you are doing multiple checks like my example its most likely the
list of "is"s plus a single cast (when matched) will be more efficient
than a list of as+null checks.

"is" *is* an as+null check, in fact. In IL, "is" compiles to:
IL_0007: ldloc.0
IL_0008: isinst [mscorlib]System.String
IL_000d: ldnull
IL_000e: cgt.un
IL_0010: ldc.i4.0
IL_0011: ceq
IL_0013: stloc.1
IL_0014: ldloc.1
IL_0015: brtrue.s IL_0024

"as Stream != null" compiles to:
IL_0024: ldloc.0
IL_0025: isinst [mscorlib]System.IO.Stream
IL_002a: ldnull
IL_002b: ceq
IL_002d: stloc.1
IL_002e: ldloc.1
IL_002f: brtrue.s IL_003e

I'm not sure what there's the additional cgt.un in the "is" case, but I
doubt that it gets as far as the generated native code...
Theres probably a break even point, say 5 ;-)

Is it fair to assume that you pulled that number out of thin air?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 28 '06 #25

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Vinodh Kumar | last post by:
I see that casting changes the value of a pointer in case of multiple inheritance.In single inheritance also it is the same know?Isn't it? Vinodh Kumar P
5
by: Suzanne Vogel | last post by:
** Isn't the 'static_cast' operator the same as traditional type casting? ie, Aren't the following ways of getting b1, b2 the same? // 'Derived' is derived from 'Base' Derived* d = new...
7
by: Jakob Bieling | last post by:
Hi, I have a question about casting and using the casted pointer: Suppose I have a 'base' class and a 'derived' class (which is derived from 'base'). Now I have this scenario: base* p1 = new...
3
by: Kurt | last post by:
i just can't figure out why something im doing is not working correctly.... public interface IInterface { int someProperty { get; set; }
0
by: Kurt Lange | last post by:
no... the array is created dynamically. and no... that defeats the purpose of what im trying todo.. encapsulate all initializing of variables in base class... derive from it... by deriving...
10
by: Brett Romero | last post by:
Say I have a class inheriting some base class: BaseClass { void Foo() { Update(); } }
9
by: Jess | last post by:
Hello, It seems both static_cast and dynamic_cast can cast a base class pointer/reference to a derived class pointer/reference. If so, is there any difference between them? In addition, if I...
9
by: Naomi | last post by:
I need to make software engineering decision to do with using a derived data type in a container class. So for example, if I have an Edge class, and I want to make a Edge object which contains two...
9
by: Taras_96 | last post by:
Hi everyone, I was experimenting with static_cast and reinterpret cast #include <iostream> struct A1 { int a; }; struct A2 { double d; }; struct B : public A1, A2
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.