Up casting (base to derived) in C#

  • Thread starter Thread starter AtariPete
  • Start date Start date
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
 
Tigger said:
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.
 
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
 
Tigger said:
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?
 
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
Tigger said:
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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top