2010-10-14 48 views
3

再次,我真的希望這不是一個意見問題;我想知道哪個是確定屬於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 - 使用是運營商

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#來完成這項工作。

EDIT 1:

我已經添加了倍率關鍵字上面的代碼。

編輯2:

對不起,我可能沒有說清楚。我會更好地說明它:

例如,我有具有Children屬性,它返回我UIElement個WPF Panel對象。我需要知道某個元素的類型是什麼類型的......在我的特殊情況下,用戶正在屏幕上繪製圖形,所以我需要知道爲了存儲需要繪製多少個節點和多少個連接然後在數據庫。不幸的是,我不能使用多態性,對吧?我如何知道是否應該將一行添加到我的節點表或我的連接表中?

+10

這是一個常見的面向對象設計的錯誤。你不需要這個。請閱讀「多態性」,然後關閉問題。 – 2010-10-14 19:51:45

+0

有很多.NET Framework中,例如,XmlDocument的/的XmlElement/...,的XDocument /的XElement/...,LambdaExpression/UnaryExpression/... – dtb 2010-10-14 20:02:11

+0

@美國洛特第一種方式的例子很多:+1 :) (blah) – leppie 2010-10-15 13:37:11

回答

0

您使用的例子是錯誤的(其他的都表示 - 使用多態),但它可以合理地問什麼類型的對象是。

我提出了類似的問題用於C++ Testing a c++ class for features

關於之間#1和#2的差別。都需要元數據。在情況1中,您正在創建它,如果情況2您正在使用由CLR製作的元數據。 CLR是它可能比你更好的,其支付該開銷反正

與往常一樣 - 如果你想知道這是更快的答案很簡單 - 測量它看看。我懷疑是有可測量的差異

+0

「詢問對象是什麼類型是合理的。」請舉例說明什麼時候它實際上是「合理的」,並不涉及漂亮多變的多態性。不幸的是,**所有**我見過的運行時類型識別的例子都是錯誤的多態錯誤。請舉例說明。 – 2010-10-15 11:14:44

+0

http://stackoverflow.com/questions/3336859/testing-a-c-class-for-features – pm100 2010-10-15 16:29:29

+0

@ PM100:這是怎麼回事還不壞多態性的另一個例子嗎?它看起來應該是簡單的多態性。我錯過了什麼? – 2010-10-15 18:38:52

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 
+0

您的意思是'GetType'而不是'TypeOf'嗎? – Gabe 2010-10-14 19:55:53

+1

多態性應根據「myObject」是Type1類型還是Type2類型而不必進行明確檢查來使*不同*發生。如果你正在使用'myObject'並且需要區分它的具體類型,那意味着你不適合地耦合它並需要重構。 – FMM 2010-10-14 21:16:26

+0

通過一切手段,你應該使用多態,如果可以的話,但是,有時你沒有這個選項。例如,LINQ給了我一個IEnumerable,但如果這是*真的*一個列表的東西,我怎麼知道,如果我不測試它? – 2010-10-14 21:40:19

10

你做錯了。有沒有聽說過多態(遲/動態綁定更準確)?父母應該有一個抽象的方法,如doSomething()由孩子實施,無論是在_doSomethingWithChild1應該在Child1.doSomething等這是什麼OO是 所有 - 好吧,不是全部,但很大一部分 - 關於! C++ FAQ是正確的,聲稱如果沒有virtual,C++將不是面向對象的。它不僅更容易/更不容易出錯添加另一個孩子(你只是定義了一個新的子類和方法,無需通過交換機或IFS撥弄),並極有可能是最快的方式可能(每JIT稱職的使用polymorphic inline caching)這也是慣用的,不太可能讓你認爲「WTF」盯;)

+0

這與switch語句實際上是一樣的。如果您正在切換運行時類型,我同意,您做錯了(TM)。四處尋找重構switch語句的多態性。 – FMM 2010-10-14 21:26:07

+0

爲了產生更清晰的例子,我編輯了這個問題。對象可能是多態的,但有些時候我需要知道它們的確切類型。 – 2010-10-16 14:20:58

+0

@布魯諾:這個例子究竟如何不適用於多態?如果你根據類型將其他東西插入到數據庫中,只需使對象(多態)將這些信息放入數據庫中? – delnan 2010-10-16 15:49:43