Há uma questão importante e sutil que nenhum deles aborda diretamente. Existem duas maneiras de considerar o tipo em C #: tipo estático e tipo de tempo de execução .
O tipo estático é o tipo de uma variável em seu código-fonte. É, portanto, um conceito de tempo de compilação. Esse é o tipo que você vê em uma dica de ferramenta ao passar o mouse sobre uma variável ou propriedade em seu ambiente de desenvolvimento.
Você pode obter o tipo estático escrevendo um método genérico auxiliar para permitir que a inferência de tipo cuide disso para você:
Type GetStaticType<T>(T x) { return typeof(T); }
O tipo de tempo de execução é o tipo de um objeto na memória. Portanto, é um conceito de tempo de execução. Este é o tipo retornado pelo GetType()método.
O tipo de tempo de execução de um objeto é frequentemente diferente do tipo estático da variável, propriedade ou método que o mantém ou retorna. Por exemplo, você pode ter um código como este:
object o = "Some string";
O tipo estático da variável é object, mas em tempo de execução, o tipo do referente da variável é string. Portanto, a próxima linha imprimirá "System.String" no console:
Console.WriteLine(o.GetType()); // prints System.String
Mas, se você passar o mouse sobre a variável oem seu ambiente de desenvolvimento, verá o tipo System.Object(ou a objectpalavra-chave equivalente ). Você também vê o mesmo usando nossa função auxiliar acima:
Console.WriteLine(GetStaticType(o)); // prints System.Object
Para variáveis do tipo de valor, como int, double, System.Guid, você sabe que o tipo de tempo de execução será sempre o mesmo que o tipo estático, porque os tipos de valor não pode servir como a classe base para outro tipo; o tipo de valor é garantidamente o tipo mais derivado em sua cadeia de herança. Isso também é verdadeiro para os tipos de referência lacrada: se o tipo estático for um tipo de referência lacrada, o valor de tempo de execução deve ser uma instância desse tipo ou null.
Por outro lado, se o tipo estático da variável for um tipo abstrato, é garantido que o tipo estático e o tipo de tempo de execução serão diferentes.
Para ilustrar isso no código:
// int is a value type
int i = 0;
// Prints True for any value of i
Console.WriteLine(i.GetType() == typeof(int));
// string is a sealed reference type
string s = "Foo";
// Prints True for any value of s
Console.WriteLine(s == null || s.GetType() == typeof(string));
// object is an unsealed reference type
object o = new FileInfo("C:\\f.txt");
// Prints False, but could be true for some values of o
Console.WriteLine(o == null || o.GetType() == typeof(object));
// FileSystemInfo is an abstract type
FileSystemInfo fsi = new DirectoryInfo("C:\\");
// Prints False for all non-null values of fsi
Console.WriteLine(fsi == null || fsi.GetType() == typeof(FileSystemInfo));
int