确定对象的类型

时间:2010-10-14 19:50:48

标签: c# polymorphism

同样,我真的希望这不是一个意见问题;我试图知道哪种是确定属于C#中某个层次结构的对象类型的最佳方法。我有两种方法来设计我的应用程序:

1 - 在基类上使用属性:

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);break;
        case TypeOfObject.Child2: _doSomethingWithChild2(p);break;
    }
}

2 - 使用is运算符

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);
}

每种选择的含义是什么?我认为2由于依赖于元数据而具有更大的性能,但是1似乎不那么优雅。此外,我学会了用C ++编写的这种方法......我不确定是否有必要使用C#。

编辑1:

我已将 override 关键字添加到上面的代码中。

编辑2:

对不起,我可能没有说清楚。我会更好地说明一下:

例如,我有一个具有Panel属性的WPF Children对象,该对象返回UIElement个。我需要知道某个元素在什么类型上行动...在我的特定情况下,用户在屏幕上绘制图形,所以我需要知道有多少节点和多少个连接被绘制以便存储然后在数据库。不幸的是,我不能使用多态性,对吗?我怎么知道是否应该在我的节点表或连接表中添加一行?

3 个答案:

答案 0 :(得分:10)

你做错了。曾经听说过多态(迟到/动态绑定更准确)?父母应该有一个像doSomething()这样的抽象方法,由孩子们实现,_doSomethingWithChild1中的Child1.doSomething应该是virtual等等。这就是OO all < / strike> - 好吧,不是全部,而是大部分 - 关于! C ++ FAQ是正确的,声称如果没有{{1}},C ++将不是面向对象的。不仅更容易/更不容易出错添加另一个孩子(你只需定义一个新的子类和方法,不需要摆弄开关或ifs)并且很可能以最快的方式(每个JIT值得它使用{{3 }},它也是惯用的,不太可能让你“WTF”凝视;)

答案 1 :(得分:4)

第一种选择不是必要的。如果您查看Object(C#中所有对象的基础),您将找到GetType()成员。

在我们的生产代码中,我们经常使用方法2,主要用于“向下转换”,即将我的基类转换为从所述基类派生的类...

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

我们还使用as运算符....

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

关于这个的好处是,你不会像你尝试过这样的事情那样得到例外:

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

答案 2 :(得分:0)

您的使用示例是错误的(正如其他人所说的那样 - 使用多态)但是询问对象的类型是合理的。

我问过c ++ Testing a c++ class for features

的类似问题

关于#1和#2之间的区别。两者都需要元数据如果您正在使用案例1,则在案例2中您仍在使用CLR生成的元数据。 CLR可能比你更好,而且无论如何都支付了开销

一如既往 - 如果你想知道哪个更快,答案很简单 - 测量并查看。我怀疑存在可衡量的差异