2013-02-13 7 views
8

Mam nadzieję, że pytanie jest poprawne, przedstawmy więc przykład. Wyobraźmy sobie następującą metodę Generic:Dlaczego VS ostrzega mnie, że typeof (T) nigdy nie jest typem podanym w ogólnej metodzie, w której parametr typu jest ograniczony do implementacji T?

public abstract class Base : IDisposable 
{ 
    public static IEnumerable<T> GetList<T>() 
     where T : Base 
    { 
     // To ensure T inherits from Base. 
     if (typeof(T) is Base) 
      throw new NotSupportedException(); 

     // ... 
    } 
} 

Według MSDN słowo kluczowe where ogranicza parametr typu T być typu Base lub dziedziczą z tej klasy.

[...] A gdzie punkt może zawierać wiązanie klasy bazowej, w którym stwierdza się, że muszą mieć do określonej klasy jako klasa podstawy (albo być tego samego klasy) w celu użycia jako typ argument dla tego rodzaju generycznego.

Również ten kod nie kompilacji:

public static T GetFirst() 
    where T : Base 
{ 
    // Call GetList explicitly using Base as type parameter. 
    return (T)GetList<Base>().First(); 
} 

więc kiedy po ostatnim Kod typeof(T) powinien powrócić Base, nie powinna? Dlaczego program Visual Studio drukuje to ostrzeżenie?

ostrzeżenie CS0184: Podane wyrażenie nigdy nie należy do podanego typu ("Demo.Base").

+0

Co chcesz zrobić? Zapewnienie, że 'T' dziedziczy z' Base' jest bezużyteczne, ponieważ ogólne ograniczenie już to zapewnia. – CodesInChaos

+0

Ograniczenie zapewnia, że ​​'T' dziedziczy po' Base' ** LUB ** jest samym 'Base'. Chcę, aby 'T' dziedziczył po' Base'. – Carsten

Odpowiedz

13

typeof(whatever) zawsze zwraca wystąpienie typu Type. Type nie pochodzi od Base.

Co chcesz to:

if(typeof(T) == typeof(Base)) 
    throw new NotSupportedException("Please specify a type derived from Base"); 

Coś, co wygląda to tak samo jest taka:

if(variableOfTypeT is Base) 

Ale to ma inne znaczenie.
Pierwsza instrukcja (z typeof(Base)) to tylko true, jeśli T jest Base. Będzie to false dla każdego typu pochodzącego z Base.
Drugie wyrażenie (variableOfTypeT is Base) jest zawsze true w klasie, ponieważ każda klasa pochodząca od Base zwróci true dla sprawdzenia swojej klasy bazowej.

+0

Alternatywa nie działa ... 'T' jest parametrem typu, ale jest używana jak zmienna;) Ale pierwsze podejście działa ... Jak to przegapiłem ?! Czasami rozwiązanie jest zbyt proste: D – Carsten

+0

@Aschratt: Masz rację, poprawiłem to. –

1

To nie jest sposób sprawdzania dziedziczenia.

typeof(T) jest typu System.Type, to nie jest Base. Aby sprawdzić, czy T pochodzi z bazy, należy użyć wartości IsSubclassOf method, takiej jak ta:

if(typeof(T).IsSubclassOf(typeof(Base)) ... 
+0

Zauważ, że zwróci 'false' jeśli' T == Base' – CodesInChaos

+0

Myślałem, że o to chodzi. Z powodu ograniczenia OP wie już, że T jest Bazą lub pochodzi z niej. – zmbq

+0

Chciałem wiedzieć, czy 'T' * jest *' Base', aby upewnić się, że tylko implementacje tej klasy abstrakcyjnej zostaną przekazane do metody. 'IsSubclassOf' wykona sprawdzanie, które już wyraziłem z ograniczeniem' where'. – Carsten

Powiązane problemy