Qual é a diferença entre System.Type e System.RuntimeType em C #?

89

Eu estava tentando fazer alguns testes de convenção hoje, e obtendo todos os tipos em um assembly (por chamada Assembly.GetTypes()), quando tropecei em algo:

System.RuntimeType:[First.Namespace.FirstClass]

Sempre que tento comparar esse tipo com typeof(FirstClass), eles não são iguais. Então, quando tento encontrar todos os tipos que contêm FirstClassum parâmetro genérico, não estou encontrando nenhum.

Qual é a diferença entre System.RuntimeTypee System.Type?

Existe alguma maneira de resolver meu problema?

Edgar Gonzalez
fonte
6
Você pode fornecer um pequeno programa que demonstre o problema que você está enfrentando?
Eric Lippert de
Eu ia, mas já obtive a resposta: P
Edgar Gonzalez

Respostas:

108

System.RuntimeTypeé uma classe concreta que deriva da classe base abstrata System.Type. Como System.RuntimeTypenão é público, você normalmente encontrará instâncias dele como System.Type.

Pode surgir confusão quando você está tentando obter o tipo de um objeto e, por engano, chamar GetType()outro objeto que representa o tipo do primeiro objeto, em vez de apenas usar esse objeto diretamente. Em seguida Type.ToString(), retornará "System.RuntimeType"quando o objeto em que é chamado estiver representando um Tipo:

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

Por exemplo, nesta postagem do blog, alguém está tentando obter o tipo de uma coluna em um banco de dados, fazendo algo assim:

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

Visto que val já é um objeto Type, val.GetType () retornará outro objeto Type que representa o tipo, System.RuntimeTimepois esse é o tipo concreto usado para representar o objeto de tipo original. A postagem do blog mostra alguns truques de reflexão desnecessários, para obter o tipo do objeto de tipo original, quando na verdade tudo o que era necessário era:

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

Portanto, se o seu Typeobjeto estiver relatando que representa um System.RuntimeType, certifique-se de não ter chamado acidentalmente GetType()um tipo que já obteve.

Ergwun
fonte
O primeiro trecho de código só verifica se o objeto é uma instância de - Typeele retornará verdadeiro mesmo se você passar typeof(int). O segundo trecho de código não funciona para comparar typeof(string).GetType()e typeof(Type).
Mark Cidade
Isso é exatamente o que eu estava procurando! Encontrei a postagem de Thomas Danecker, mas não a de Doogal Bell
Edgar Gonzalez,
1
@Mark Cidade. Bem localizado, obrigado. Fixou a resposta para ser mais útil, esperançosamente esclarecendo qualquer confusão que apresentei citando aquela postagem do blog.
Ergwun,
@Edgar Gonzalez: Aquela postagem do blog que mencionei era na verdade um tanto enganosa. Por favor, veja minha resposta atualizada para melhores informações.
Ergwun,
4

Da resposta para Different between System.Type and System.RuntimeType de Thomas Danecker :

System.Type é uma classe base abstrata. O CLR tem sua implementação concreta no tipo interno System.RuntimeType. Por causa disso typeof (string) .GetType () retorna um RuntimeType, mas typeof (Type) retorna um Type normal. Usando o método .Equals, na verdade, um objeto.ReferenceEquals que retorna falso. Para obter os resultados esperados, você pode usar type.IsInstanceOfType (element). Isso também retornará verdadeiro se o elemento for de um tipo derivado. Se você quiser verificar o tipo exato, o valor de retorno false do seu método é o resultado desejado. Você também pode usar checkType (arrayType, Type.GetType ("System.RuntimeType")) para verificar o RuntimeType.

John Saunders
fonte
1
"faz de fato um" - Podemos fazer uma correção gramatical. Isso é o ponto crucial de tudo e não faz sentido.
N73k de
2

Em resumo...

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

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

A maneira como penso agora é que System.Typeé um tipo base para o tipo que representa os resultados da solicitação do tipo de objeto em tempo de execução, a saber System.RuntimeType. Portanto, quando você solicita o tipo de um objeto, como em "".GetType(),, a instância de System.Typeretornado é seu descendente System.RuntimeType,. Na verdade, deve-se esperar que o typeof(System.Type).GetType()também seja System.RuntimeType, mas acho que a estrutura evita especificamente isso ... simetria.

George
fonte