Jaka jest różnica między System.Type i System.RuntimeType w C #?


89

Próbowałem dzisiaj zrobić kilka testów konwencji i uzyskać wszystkie typy w zestawie (przez wywołanie Assembly.GetTypes()), gdy natknąłem się na coś:

System.RuntimeType:[First.Namespace.FirstClass]

Ilekroć próbuję porównać ten typ z typeof(FirstClass), nie są one równe. Tak więc, kiedy próbuję znaleźć wszystkie typy, które zawierają FirstClassjako parametr ogólny, nie znajduję żadnego.

Jaka jest różnica między System.RuntimeTypei System.Type?

Czy jest jakiś sposób na rozwiązanie mojego problemu?


6
Czy możesz podać mały program, który pokaże Twój problem?
Eric Lippert

Miałem zamiar, ale już dostałem odpowiedź: P
Edgar Gonzalez

Odpowiedzi:


108

System.RuntimeTypejest konkretną klasą wywodzącą się z abstrakcyjnej klasy bazowej System.Type. Ponieważ System.RuntimeTypenie jest publiczny, zazwyczaj napotkasz jego wystąpienia jakoSystem.Type .

Nieporozumienie może powstać, gdy próbujesz uzyskać typ obiektu i omyłkowo wywołujesz GetType()inny obiekt reprezentujący typ pierwszego obiektu, zamiast po prostu używać tego obiektu bezpośrednio. Następnie Type.ToString()zwróci, "System.RuntimeType"gdy wywoływany obiekt reprezentuje Type:

string str = string.Empty;
Type strType = str.GetType();
Type strTypeType = strType.GetType();
strType.ToString();     // returns "System.string"
strTypeType.ToString(); // returns "System.RuntimeType"

Na przykład w tym poście na blogu ktoś próbuje uzyskać typ kolumny w bazie danych, robiąc coś takiego:

object val = reader.GetFieldType(index);
Type runtimeType = val.GetType();
PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
Type type = (Type)propInfo.GetValue(val, null);

Ponieważ val jest już obiektem Type, val.GetType () zwróci inny obiekt Type reprezentujący typ, System.RuntimeTimeponieważ jest to konkretny typ używany do reprezentowania pierwotnego obiektu typu. W poście na blogu pokazano następnie niepotrzebną sztuczkę refleksji, aby uzyskać typ obiektu typu oryginalnego, podczas gdy tak naprawdę wszystko, co było wymagane, to:

Type type = reader.GetFieldType(index) as Type;

Więc jeśli twój Typeobiekt zgłasza, że ​​reprezentuje a System.RuntimeType, upewnij się, że nie wywołałeś przypadkowo GetType()typu, który już masz.


Pierwszy fragment kodu sprawdza tylko, czy obiekt jest instancją - Typezwróci wartość true, nawet jeśli zdasz typeof(int). Drugi fragment kodu nie działa w przypadku porównywania typeof(string).GetType()i typeof(Type).
Mark Cidade

To jest dokładnie to, czego szukałem! Znalazłem post Thomasa Daneckera, ale nie Doogal Bell's
Edgar Gonzalez

1
@Mark Cidade. Dobrze zauważone, dzięki. Ustaliłem odpowiedź, aby była bardziej pomocna, miejmy nadzieję, że wyjaśnię wszelkie zamieszanie, które wprowadziłem, cytując ten post na blogu.
Ergwun

@Edgar Gonzalez: Ten post na blogu, o którym wspomniałem, był raczej mylący. Zobacz moją zaktualizowaną odpowiedź, aby uzyskać lepsze informacje.
Ergwun,

4

Od odpowiedzi do Różnica między System.Type i System.RuntimeType autorstwa Thomasa Daneckera :

System.Type jest abstrakcyjną klasą bazową. Środowisko CLR ma swoją konkretną implementację w typie wewnętrznym System.RuntimeType. Z tego powodu typeof (string) .GetType () zwraca RuntimeType, ale typeof (Type) zwraca normalny Type. Użycie metody .Equals powoduje w rzeczywistości obiekt.ReferenceEquals, który zwraca wartość false. Aby uzyskać oczekiwane wyniki, możesz użyć type.IsInstanceOfType (element). Zwróci to również wartość true, jeśli element jest typu pochodnego. Jeśli chcesz sprawdzić dokładny typ, pożądanym wynikiem jest zwracana wartość false twojej metody. Możesz również użyć funkcji checkType (arrayType, Type.GetType ("System.RuntimeType")), aby sprawdzić RuntimeType.


1
„faktycznie robi” - czy możemy uzyskać poprawkę gramatyczną. To jest sedno całej sprawy i nie ma to sensu.
N73k

2

W skrócie...

    "".GetType().ToString()           == "System.String"

    "".GetType().GetType().ToString() == "System.RuntimeType"

Sposób, w jaki teraz o tym myślę, jest taki, że System.Typejest to typ podstawowy dla typu, który reprezentuje wyniki żądania typu obiektu w czasie wykonywania, a mianowicie System.RuntimeType. Więc, kiedy zażądać od rodzaju obiektu, jak w, "".GetType(), wystąpienie System.Typezwrócony jest jego potomkiem, System.RuntimeType. W rzeczywistości, należy spodziewać się, że typeof(System.Type).GetType()powinno być System.RuntimeTypetak dobrze, ale myślę, że ramy specjalnie zapobiega to ... symetrię.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.