user41685
user41685

Reputation: 43

best way to check class

I have a method which is taking in a parameter that is a Interface object

like this

private void SomeMethod(InterfaceA IUA)

Inside the method I have a statement like this

ClassD someVar = (ClassD)(((ClassC)((ClassB)IUA)).D);

everything if fine and dandy. However, in certain cases the object IUA might be instance of ClassZ rather than ClassB. So in that case the above line errors out. Is there a way to find out, before doing above statement, that which class does the object really belong to? If i know that before hand then I can have an If statement and do the following

ClassZ someVar = (ClassD)(((ClassC)((ClassZ)IUA)).Z);

I come from java background...In java i know we have getClass() ...what would be the equivalent in .net?

Upvotes: 0

Views: 217

Answers (10)

Roger Lipscombe
Roger Lipscombe

Reputation: 91865

You really shouldn't be writing code like this without good reason.

That said: you can use is

if (a is ClassB)
{
    ClassB b = (ClassB)a;
}
else if (a is ClassZ)
{
    ClassZ z = (ClassZ)a;
}

...or as:

ClassB b = a as ClassB;
if (b != null)
{
    // ...
}

Upvotes: 7

George Mauer
George Mauer

Reputation: 122132

You should use method overloading, this is how it should look:

private void SomeMethod(ClassB obj) {
  DoMoreStuff(obj.B);
}
private void SomeMethod(ClassZ obj) {
  DoMoreStuff(obj.Z);
}
private void  DoMoreStuff(int val) {
 // ..
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500983

Okay, a few different options here:

  • The equivalent for Java's getClass() is GetType(); you can use typeof(...) to retrieve the Type object for a type you know at compile-time. This isn't the best way of testing things though, unless you're interested in exact equality.

  • The equivalent of Java's instanceof operator is the is operator in C#:

    if (x is SomeType) ...
    

    This can be used with boxed values to check for value types, too:

    if (x is int) ...
    
  • A related operator is the as operator, which doesn't return true or false, but a reference of the type specified. The type has to be a nullable type (reference or nullable value type) and the result is the original value but strongly typed as the target type if the value is a reference of an appropriate type, or null otherwise. For instance:

    object x = "hello";
    
    string y = x as string; // y = "hello" now
    Stream z = x as Stream; // z = null now
    

    In the case where you want to check whether or not a reference is of a particular type, and then use it as a reference of that type, a common pattern is:

    object x = GetObjectFromSomewhere();
    string y = x as string;
    if (y != null)
    {
        Console.WriteLine(y.Length); // Whatever
    }
    

    This is more efficient than the equivalent to what's required in Java:

    object x = GetObjectFromSomewhere();
    if (x is string)
    {
        string y = (string) x;
        Console.WriteLine(y.Length); // Whatever
    }
    
  • If it's a bug for the reference to be of the wrong type, just cast - that way you'll get an exception thrown if you've got a bug, which is almost certainly the best course of action at that point.

Upvotes: 1

Matt Davison
Matt Davison

Reputation: 1552

What is the point of passing the interface if your just going to cast it away? You might want to re-evaluate the design as code like this defeats the purpose of polymorphism. Also you should not use 'is' to test the type. Since you are going to cast the object anyway you should use 'as' and test for null.

Upvotes: 1

Jacek Ławrynowicz
Jacek Ławrynowicz

Reputation: 2700

From MSDN:

 public static void Test (object o) 
   {
      Class1 a;
      Class2 b;

      if (o is Class1) 
      {
         Console.WriteLine ("o is Class1");
         a = (Class1)o;
         // do something with a
      }

      else if (o is Class2) 
      {
         Console.WriteLine ("o is Class2");
         b = (Class2)o;
         // do something with b
      }

      else 
      {
         Console.WriteLine ("o is neither Class1 nor Class2.");
      }
   }

Upvotes: 0

Mitchel Sellers
Mitchel Sellers

Reputation: 63126

You could do something like

If (IUA is ClassB)
    //I am class b

However, given that your method is taking an interface, I would question your design if you are looking to get back to the actual concrete type. Can you re-factor to create an interface method that you can use to perform the actions of that method.

Upvotes: 0

George Mauer
George Mauer

Reputation: 122132

How about

if(IUA is ClassB)
  someVar = (IUA as ClassB).B;
elseif (IUA is ClassZ)
  someVar = (IUA as ClassZ).Z;

That should work, though you get the mandatory scolding that this is a rather poor architecture.

Upvotes: 1

axel_c
axel_c

Reputation: 6796

You can do

if (someVar is ClassZ)

Which returns TRUE if someVar is-a ClassZ,

or

someVar.GetType ()

to get the actual class

Upvotes: 1

Vojislav Stojkovic
Vojislav Stojkovic

Reputation: 8153

Well, for starters, you're not really supposed to downcast from interface to a class, unless you have a really good reason to do so. If you need ClassD functionality, then your method should receive ClassD, not InterfaceA.

Another thing that confuses me is the multiple downcasting. I use both Java and C# and I've never seen the need to do a multiple cast like that.

Finally, you could use operator "is" to find out whether certain type inherits from a certain class or implements a certain interface, as in

if (IUA is ClassD)
{
    // do something
}

Upvotes: 6

Joe Phillips
Joe Phillips

Reputation: 51150

I don't think it's necessary to cast IUA to ClassB. You're not using any of the ClassB methods as far as I can tell.

Upvotes: 0

Related Questions