Trexer
Trexer

Reputation: 31

c# casting with is and as

I need some help. It is pretty easy. I have this piece of code, and I would like to discuss if it is correct, or if you suggest a better way to do it. I have an idea about the answer but I would like to see your answers. here it goes

if (myObject is ClassA)
{
    var myObjectA = myObject as ClassA;
    myObjectA?.MethodJustInA();
}
else if (myObject is ClassB)
{
    var myObjectB = myObject as ClassB;
    myObjectB?.MethodJustInB();
    myObjectB?.OtherMethodJustInB();
}

I think there is no need to create a new object after every if, just doing:

(ClassB)myObjectB.MethodJustInB();

And there is no need to check it is null since if it is within the if is because is not null

Thanks

Upvotes: 2

Views: 3682

Answers (5)

Sinatr
Sinatr

Reputation: 22008

If you are testing for multiple types, then as+null check is more efficient (just one cast, instead of is + casting):

var a = myObject as ClassA;
if (a != null)
    a.MethodJustInA();
var b = myObject as ClassB;
if (b != null)
    b.MethodJustInB();

In given scenario I'd even make local scope like this

{
    var obj = myObject as ClassA;
    if (obj != null)
        obj.MethodJustInA();
}
{
    var obj = myObject as ClassB;
    if (obj != null)
        obj.MethodJustInB();
}

{ } make it possible to reuse same variable name (easier to copy/paste and, in my oppinion, read).


I was a bit rushy and haven't thought well about else case (when myObject is ClassA you don't want to cast it as b, etc.). Normally I'd do return after each successful if and corresponding method call. I am not able to construct nice looking if/else if code otherwise.


Another idea is to use C# 6.0 null-conditional operator:

(myObject as ClassA)?.MethodJustInA();
(myObject as ClassB)?.MethodJustInB();

That looks really neat, but it will do unnecessarily casting to B and has side-effect: if ClassB inherits ClassA, then both methods will be called because both casts will success.

Note: mentioned side effect unfortunately applies to all proposed snippets.

Upvotes: 1

Jeroen van Langen
Jeroen van Langen

Reputation: 22083

If you're using it this way, you only need to cast it ones:

var myObjectA = (myObject as ClassA);

if (myObjectA != null)
{
    myObjectA.MethodJustInA();
} 
else
{
    var myObjectB = (myObject as ClassB);

    if (myObjectB != null)
    {
        myObjectB.MethodJustInB();
    }
}

And in C# 7.0 you can do:

if (myObject is ClassA myObjectA)
    myObjectA.MethodJustInA();
else 
    if (myObject is ClassB myObjectB)
        myObjectB.MethodJustInB();

Upvotes: 6

Metoniem
Metoniem

Reputation: 249

Within those if statements you can just cast your object like this:

var myObjectB = (ClassB)myObject;

or cast it directly:

((ClassB)myObject).MethodJustInB();

Upvotes: 0

Patrick Hofman
Patrick Hofman

Reputation: 157136

There are some optimizations possible.

  • If myObject is ClassA, you don't need the soft cast. Instead you can do the cast directly: var myObjectA = (ClassA)myObject;.
  • Since that is the case, and you just call a single method, you don't need to assign a new variable: ((ClassA)myObject)?.MethodJustInA();.
  • And because myObject is ClassA evaluates to false if myObject is null, you don't need to do the check again: ((ClassA)myObject).MethodJustInA();.

So:

if (myObject is ClassA)
{
    ((ClassA)myObject).MethodJustInA();
}
else if (myObject is ClassB)
{
    var myObjectB = (ClassB)myObject;
    myObjectB.MethodJustInB();
    myObjectB.OtherMethodJustInB();
}

Upvotes: 4

Georg Patscheider
Georg Patscheider

Reputation: 9463

I prefer to cast with as and then check for null, this way you can skip the is check. Also, you do not need the elvis operator ?. because you know the object is not null.

var myObjectA = myObject as ClassA;
var myObjectB = myObject as ClassB;
if (myObjectA != null)
{
    myObjectA.MethodJustInA();
}
else if (myObjectB != null)
{
    myObjectB.MethodJustInB();
    myObjectB.OtherMethodJustInB();
}

Upvotes: 2

Related Questions