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). 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?
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;
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?
"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
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.
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.
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. :)
"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
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."
"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
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
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.
so where does this leave us. how might I up cast then the base class
isn't instantiated with the derived type?
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
"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
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
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.
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
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
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
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
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
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
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
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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
|
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...
|
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...
|
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;
}
|
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...
|
by: Brett Romero |
last post by:
Say I have a class inheriting some base class:
BaseClass
{
void Foo()
{
Update();
}
}
|
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...
|
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...
|
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
|
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,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
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$) {
}
...
|
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...
|
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...
|
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
|
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...
|
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...
|
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...
| |