开发者

Determining a Type of an Object

开发者 https://www.devze.com 2023-01-19 21:24 出处:网络
Again, I really hope this isn\'t a matter of opinion; I\'m trying to know which is the best way to determine the type of an object that belongs to a certain hierarchy in C#. I have two ways to design

Again, I really hope this isn't a matter of opinion; I'm trying to know which is the best way to determine the type of an object that belongs to a certain hierarchy in C#. I have two ways to design my application:

1 - Use a property on the base class:

public abstract class Parent 
{
    public abstract TypeOfObject TypeOfObject { get; }
}

public class Child1 : Parent
{
    public override TypeOfObject TypeOfObject { get { return TypeOfObject.Child1 } }

    // ...
}

public class Child2 : Parent
{
    public override TypeOfObject TypeOfObject { get { return TypeOfObject.Child2 } }

    // ...
}

public enum TypeOfObject 
{
    Child1,
    Child2
}

public static void Main()
{
    Parent p = new Child1();

    switch (p.TypeOfObject)
    {
        case TypeOfObject.Child1: _doSomethingWithChild1(p);bre开发者_如何学Goak;
        case TypeOfObject.Child2: _doSomethingWithChild2(p);break;
    }
}

2 - Use the is operator

public abstract class Parent 
{
    // ...
}

public class Child1 
{
    // ...
}


public class Child2 : Parent
{    
    // ...
}

public enum TypeOfObject 
{
    Child1,
    Child2
}

public static void Main()
{
    Parent p = new Child1();

    if (p is Child1) _doSomethingWithChild1(p);
    if (p is Child2) _doSomethingWithChild2(p);
}

What are the implications of each alternative? I think 2 has a greater performance hit since it relies on metadata, but 1 seems way less elegant. Besides, I learned to do this the 1 way in C++... I'm not sure it's necessary to do so with C#.

EDIT 1:

I've added the override keyword to the code above.

EDIT 2:

I'm sorry, I've probably not made myself clear. I will illustrate it better:

For example, I have a WPF Panel object that has a Children property, which returns me UIElements. I need to know what type a certain element is to act upon it... in my particular case, the user is drawing a graph on the screen, so I need to know how many nodes and how many connections are drawn in order to store then at the database. I can't, unfortunately, use polymorphism for that, right? How will I know if I should add a line to my nodes table or to my connections table?


You are doing it wrong™. Ever heard of polymorphism (late/dynamic binding to be more precise)? The parent should should have an abstract method like doSomething() to be implemented by the children, whatever was in _doSomethingWithChild1 should be in Child1.doSomething, etc. This is what OO is all - well, not all, but to a large part - about! The C++ FAQ is right claiming that C++ wouldn't be object oriented without virtual. Not only it's easier/less error-prone to add another child (you just define a new subclass and the method, no need to fiddle with switches or ifs) and very likely the fastest way possible (every JIT worth its salt uses polymorphic inline caching), it's also idiomatic and less likely to get you that "WTF" stare ;)


the first alternative is not neccessary. if you look at Object (the base for ALL objects in C#) you will find a GetType() member.

In our production code, we frequently use method 2, mainly for "down-casting" that is, casting my a base class to a class that is derived from said base class...

if ( myObject is Type1 ) dosomething();
if ( myObject is Type2 ) dosomethingelse();

we also use the as operator....

Type1 object1 = someotherobject as type1;
if ( object1 != null ) dosomething();

the nice thing about this, is that you won't get exceptions like you would if you tried something like this:

((TypeFoo)object1).bar(); // if object 1 is NOT of TypeFoo you get an exception


Your use examples are wrong (as other have said - use polymorphism) but it can be reasonable to ask what type an object is.

I asked a similar question for c++ Testing a c++ class for features

Regarding the difference between #1 and #2. Both require metadata. In case 1 you are making it, in case 2 you are using metadata made by the CLR anyway. The CLR is probably better at it than you , and its paying that overhead anyway

As always - if you want to know which is faster the answers is simple - measure it and see. I doubt there is a measurable difference

0

精彩评论

暂无评论...
验证码 换一张
取 消