2009-08-02 17 views
11

Zacznę od wyjaśnienia, mój scenariusz w kodzie:C# .NET - Jak mogę uzyskać typeof() do pracy z dziedziczeniem?

public class A { } 

public class B : A { } 

public class C : B { } 

public class D { } 

public class Test 
{ 
    private A a = new A () ; 
    private B b = new B () ; 
    private C c = new C () ; 
    private D d = new D () ; 

    public Test () 
    { 
     // Evaluates to "false" 
     if (a.GetType == typeof(B)) { } //TODO: Add Logic 

     // Evaluates to "true" 
     if (b.GetType == typeof(B)) { } //TODO: Add Logic 

     // I WANT this to evaluate to "true" 
     if (c.GetType == typeof(B)) { } //TODO: Add Logic 

     // Evaluates to "false" 
     if (d.GetType == typeof(B)) { } //TODO: Add Logic 
    } 
} 

Ważną linia zwracać uwagę tutaj jest:

if (c.GetType == typeof(B)) { } 

Wierzę, że będzie to w rzeczywistości ocenić na " false ", ponieważ typeof (B) i typeof (C) nie są sobie równe w obu kierunkach. (C jest B, ale B niekoniecznie jest C.)

Ale potrzebuję jakiegoś warunku, który to uwzględni. Jak mogę stwierdzić, czy obiekt jest B, czy cokolwiek z tego wynika?

Nie obchodzi mnie, czy jest to obiekt POZBAWIONY od B, o ile jest tam podstawowa klasa B. I nie mogę przewidzieć, co klasa pochodna może pojawić się w mojej aplikacji. Muszę tylko założyć, że nieznane klasy pochodne mogą istnieć w przyszłości - i dlatego mogę skupić się tylko na upewnieniu się, że klasa bazowa jest tym, czego oczekuję.

Potrzebuję warunku, który wykona dla mnie tę kontrolę. Jak to osiągnąć?

+0

W miarę możliwości należy unikać tego rodzaju logiki. Kiedy musisz określić, jaki jest pochodny typ obiektu, nie korzystasz z polimorfizmu. –

+0

Zobacz mój komentarz na odpowiedź Steven Sudit. – Giffyguy

Odpowiedz

36

można po prostu użyć is:

if (c is B) // Will be true 

if (d is B) // Will be false 
+0

W odpowiedzi na jedyne faktyczne pytanie w PO: "Jak mogę stwierdzić, czy obiekt jest B, czy cokolwiek z tego wynika?" to jest poprawna odpowiedź. Mój jest odpowiedzią na tytuł wątku, ale mniej odpowiedni dla opisanego problemu. –

+0

Ah, to prawda. Masz rację, moje pytanie jest trochę zakręcone. Mój błąd. – Giffyguy

+0

+1 To jest właściwe rozwiązanie tego problemu. –

19

Edytuj: odpowiada na pytanie w tytule wątku. cdm9002 ma lepszą odpowiedź na problem, jak opisano w pełnym poście.

typeof(B).IsAssignableFrom(c.GetType()) 
+2

Odpowiedź od cdm9002 jest lepsza, ponieważ nie używa refleksji. –

+0

@pb: Jeśli chcesz uzyskać informacje techniczne, druga odpowiedź nie używa 'typeof' z dziedziczeniem. Jak widać z mojej edycji, nie jestem osobą, która twierdzi, że pierwsza odpowiedź, którą uważam za najbardziej odpowiednią.:) –

+2

Jest to nie tylko idealnie poprawna odpowiedź, ale dodatkowo obejmuje przypadek, gdy nie masz instancji żadnej z klas pod ręką, ale nadal chcesz ustalić, czy istnieje relacja dziedziczenia między dwoma typami. –

4

To wygląda na zadanie dla polimorfizmu, w przeciwieństwie do wielkiego switch z testów dla poszczególnych klas.

+0

Rzeczywiście. Umieść metodę wirtualną na klasie A, zastąp ją odpowiednio w podklasach, a następnie wywołaj tę metodę wirtualną. –

+1

Jak nieuprzejmi !! Ha ha. Moja logika klasowa nie wygląda tak, jak ten bałagan. Po prostu musiałem wymyślić, jak wykonać ten warunek. Piszę metodę PropertyChangedCallback W abstrakcyjnej klasie bazowej i potrzebuję warunku bezpieczeństwa, który zapewni, że parametr DependencyObject jest obiektem wywodzącym się z mojej klasy bazowej. Jeśli nie, zgłaszam błąd lub anuluję logikę. Polimorfizm nie jest pomocny w tym przypadku. – Giffyguy

+1

OK, wystarczy użyć "jest". –

0

Dla VB.NET Visual Studio     2008, można sprawdzić to lubią:

'MyTextBox control is inherited by Textbox 
If Ctl.GetType.Name = "MyTextBox" then  

End If 
1

Jako alternatywę dla kontroli (c is B), można również wykonać następujące czynności:

var maybeB = c as B; 
if (maybeB != null) { 
    // make use of maybeB 
} 

Jest to preferowane w niektórych przypadkach, ponieważ aby korzystać z c jako B podczas korzystania z is, i tak musiałbyś rzucić.

0
typeof(B).IsInstanceOfType(c) 

Podobne do odpowiedzi powyżej z Sam-Harwell, czasami może być typu „B” w zmiennej, więc trzeba użyć refleksji zamiast „jest” operatora.

Użyłem rozwiązania Sama i byłem mile zaskoczony, gdy Resharper zrobił tę sugestię.

Powiązane problemy