Tipos (guia de programação de C#)

Tipos, variáveis e valores

C# é uma linguagem fortemente tipada. Cada variável e constante tem um tipo, como cada expressão que avalia um valor. Cada assinatura do método Especifica um tipo para cada parâmetro de entrada e o valor de retorno. A.NET Framework class library define um conjunto de tipos numéricos internos, como também os tipos mais complexos que representam uma ampla variedade de construções lógicas, como, por exemplo, sistema de arquivos, conexões de rede, coleções e matrizes de objetos e as datas. Um programa C# típico usa tipos da biblioteca de classes bem como tipos definidos pelo usuário que modelam os conceitos que são específicos para o domínio do problema do programa.

As informações armazenadas em um tipo podem incluir o seguinte:

  • O espaço de armazenamento que necessita de uma variável do tipo.

  • Os valores máximo e mínimos que ela pode representar.

  • Os membros (métodos, campos, eventos e assim por diante) que ele contém.

  • O tipo base que ela herda.

  • O local de memória onde as variáveis serão alocadas em tempo de execução.

  • Os tipos de operações que são permitidos.

O compilador usa as informações de tipo para certificar-se de que todas as operações são executadas em seu código são segurança de tipos. Por exemplo, se você declarar uma variável do tipo int, o compilador permite que você use a variável além e operações de subtração. Se você tentar executar essas operações mesmas em uma variável do tipo bool, o compilador gera um erro, como mostrado no exemplo a seguir:

int a = 5;             
int b = a + 2; //OK

bool test = true;

// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
int c = a + test;
ObservaçãoObservação

Os desenvolvedores de c e C++, observe que, em C#, bool não pode ser convertido para int.

O compilador incorpora informações de tipo no arquivo executável como metadados. O common language runtime (CLR) usa esses metadados em tempo de execução para garantir mais segurança de tipo quando ele aloca e recupera da memória.

Especificando tipos nas declarações de variável

Quando você declarar uma variável ou constante em um programa, você deve especificar o tipo ou use o var palavra-chave para permitir que o compilador a inferir o tipo. O exemplo a seguir mostra algumas declarações de variáveis que usam tipos numéricos internos e tipos definidos pelo usuário:

// Declaration only:
float temperature;
string name;
MyClass myClass;

// Declaration with initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = { 0, 1, 2, 3, 4, 5 };
var query = from item in source
            where item <= limit
            select item;

Os tipos de parâmetros do método e valores de retorno são especificados na assinatura do método. A assinatura a seguir mostra um método que requer um int como um argumento de entrada e retorna uma seqüência de caracteres:

public string GetName(int ID)
{
    if (ID < names.Length)
        return names[ID];
    else
        return String.Empty;
}
private string[] names = { "Spencer", "Sally", "Doug" };

Depois que uma variável for declarada, ela não pode ser redeclarada com um novo tipo e ela não pode ser atribuída a um valor que não é compatível com seu tipo declarado. Por exemplo, você não pode declarar um int e atribua a ela um valor booleano true. No entanto, valores podem ser convertidos a outros tipos, por exemplo quando eles são atribuídos a variáveis novas ou passados como argumentos de método. A conversão de tipo que faz a perda de dados de causa não é executada automaticamente pelo compilador. Uma conversão que pode causar a perda de dados requer um cast o código-fonte.

Para obter mais informações, consulte Elenco e conversões de Tipo (guia de programação de C#).

Tipos internos

C# fornece um conjunto padrão de internos tipos numéricos para representar inteiros, flutuante, valores de ponto, expressões booleanas, caracteres de texto, valores decimais e outros tipos de dados. Também há interno string e object tipos. Eles estão disponíveis para uso em qualquer programa C#. Para obter mais informações sobre os tipos internos, consulte Types Reference Tables (C# Reference).

Tipos personalizados

Você pode usar o struct, classe, interface, e enum construções para criar seus próprios tipos personalizados. A.NET Framework propriamente dito é uma coleção de tipos personalizados fornecidos pela Microsoft que você pode usar em seus próprios aplicativos. Por padrão, os tipos mais freqüentemente usados na biblioteca de classes estão disponíveis em qualquer programa C#. Outras ficam disponíveis somente quando você adiciona uma referência de projeto ao assembly no qual são definidos explicitamente. Depois que o compilador não tem uma referência ao assembly, você pode declarar variáveis (e constantes) dos tipos declarados no assembly no código-fonte. Para obter mais informações, consulte Biblioteca de classes .NET Framework.

Common Type System

É importante compreender os dois pontos fundamentais sobre o sistema de tipo na .NET Framework:

  • Ele suporta o princípio de herança. Tipos podem derivar de outros tipos, chamados tipos base. O tipo derivado herda (com algumas restrições), os métodos, propriedades e outros membros do tipo base. Por sua vez, o tipo base pode derivar de algum outro tipo, no qual o caso o tipo derivado herda os membros de ambos os tipos base em sua hierarquia de herança. Todos os tipos, incluindo tipos numéricos internos, como System.Int32 (palavra-chave C#: int), derivam, por fim, a partir de um único tipo de base, que é System.Object (palavra-chave C#: objeto). Essa hierarquia de tipo unificada é chamada de Common Type System (CTS). Para obter mais informações sobre herança em C#, consulte Inheritance (C# Programming Guide).

  • Cada tipo do CTS é definido como um o tipo de valor ou tipo de referência. Isso inclui todos os tipos personalizados na.NET Framework e também seus próprios tipos definidos pelo usuário. Tipos que você define usando o struct palavra-chave são tipos de valor; todos os tipos numéricos internos são structs. Tipos que você define usando o classe palavra-chave são referência tipos. Tipos de referência e valor têm regras diferentes do tempo de compilação e o comportamento de tempo de execução diferente.

A ilustração a seguir mostra a relação entre os tipos de valor e tipos de referência no CTS.

Tipos de valor e a referência a tipos no CTS

Tipos de valores e tipos de referências

ObservaçãoObservação

Você pode ver que os tipos mais comumente usados são todos organizados na System namespace. No entanto, o namespace no qual um tipo contido não tem nenhuma relação de é um valor tipo ou tipo de referência.

Tipos de valor

Derivam de tipos de valor de System.ValueType, que é derivada de System.Object. Tipos que derivam de System.ValueType têm um comportamento especial no CLR. As variáveis do tipo de valor contêm diretamente os seus valores, que significa que a memória é alocada embutido no contexto de variável é declarada. Não há nenhuma alocação de heap separada ou uma sobrecarga de coleta de lixo para variáveis do tipo de valor.

Há duas categorias de tipos de valor: estrutura e enum.

Os tipos numéricos internos são structs e têm propriedades e métodos que você pode acessar:

// Static method on type Byte.
byte b = Byte.MaxValue;

Mas você declara e atribuir valores a eles como se fossem os tipos de não-agregada simples:

byte num = 0xA;
int i = 5;
char c = 'Z';

Tipos de valor são lacrado, que significa que, por exemplo, se você não pode derivar um tipo de System.Int32, e não é possível definir uma struct herdar de qualquer classe definida pelo usuário ou struct, porque uma struct só pode herdar de System.ValueType. No entanto, uma struct pode implementar uma ou mais interfaces. Você pode converter um tipo de struct para um tipo de interface; Isso faz com que uma boxing operação para quebrar o struct dentro de um objeto do tipo de referência no heap gerenciado. Operações de conversão boxing ocorrem quando você passa um tipo de valor para um método que leva um System.Object como um parâmetro de entrada. Para obter mais informações, consulte Boxing e Unboxing (C# guia de programação).

Você pode usar o struct palavra-chave para criar seus próprios tipos de valor personalizado. Normalmente, uma struct serve como um recipiente para um pequeno conjunto de variáveis relacionadas, como mostrado no exemplo a seguir:

public struct CoOrds
{
    public int x, y;

    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}

Para obter mais informações sobre estruturas, consulte Structs (C# Programming Guide). Para obter mais informações sobre os tipos de valor na .NET Framework, consulte Common Type System.

A categoria outros tipos de valor é enum. Enum define um conjunto de constantes nomeadas de integrais. Por exemplo, o enumeração deSystem.IO.FileMode na.NET Framework class library contém um conjunto de chamada de constantes inteiros que especifica como um arquivo deve ser aberto. Ele é definido como mostrado no exemplo a seguir:

public enum FileMode
{
    CreateNew = 1,
    Create = 2,
    Open = 3,
    OpenOrCreate = 4,
    Truncate = 5,
    Append = 6,
}

O System.IO.FileMode.Create a constante tem um valor de 2. No entanto, o nome é muito mais significativo para os humanos lendo o código-fonte e, pelo que o motivo é melhor usar enumerações em vez de números de literais constantes. Para obter mais informações, consulte System.IO.FileMode.

Todos os enums herdar de System.Enum, que herda de System.ValueType. Também aplicam todas as regras que se aplicam às structs enums. Para obter mais informações sobre as enumerações, consulte Tipos de enumeração (guia de programação de C#).

Tipos de referência

Um tipo que é definido como um classe, delegar, matriz, ou interface é um tipo de referência. Em tempo de execução quando você declara uma variável de um tipo de referência, a variável contém o valor Nulo até que você cria uma instância do objeto explicitamente usando a nova operador, ou atribuir a ele um objeto que tenha sido criado em outro lugar usando new, as shown in the following example:

MyClass mc = new MyClass();
MyClass mc2 = mc;

Uma interface deve ser inicializada em conjunto com um objeto de classe que implementa a ele. Se MyClass implementa IMyInterface, você poderá criar uma instância de IMyInterface conforme mostrado no exemplo a seguir:

IMyInterface iface = new MyClass();

Quando o objeto é criado, a memória é alocada no heap gerenciado e a variável armazena apenas uma referência para o local do objeto. Os tipos no heap gerenciado requerem sobrecarga quando eles são alocados e quando eles são recuperados pela funcionalidade de gerenciamento automático de memória do CLR, que é conhecido como coleta de lixo. Entretanto, a coleta de lixo também altamente otimizada e na maioria dos cenários não cria um problema de desempenho. Para obter mais informações sobre a coleta de lixo, consulte Gerenciamento automático de memória.

Todos os arrays são tipos de referência, mesmo se os seus elementos são tipos de valor. Arrays implicitamente derivam de System.Array classe, mas você declarar e usá-los com a sintaxe simplificada que é fornecida pela C#, conforme mostrado no exemplo a seguir:

// Declare and initialize an array of integers.
int[] nums = { 1, 2, 3, 4, 5 };

// Access an instance property of System.Array.
int len = nums.Length;

Tipos de referência totalmente aceitam herança. Quando você cria uma classe, você pode herdar de qualquer outra interface ou classe não está definido como lacrado, e outras classes podem herdar de classe e substituem os métodos virtuais. Para obter mais informações sobre como criar suas próprias classes, consulte Classes e estruturas (guia de programação de C#). Para obter mais informações sobre herança e métodos virtuais, consulte Inheritance (C# Programming Guide).

Tipos de valores literais

C#, valores literais recebem um tipo de compilador. Você pode especificar como um literal numérico deverá ser digitado, anexando uma letra ao final do número. Por exemplo, para especificar que o valor de 4.56 deve ser tratado como uma float, acrescentar "f" ou "F" Após o número: 4.56f. Se nenhuma letra for anexada, o compilador irá inferir um tipo para o literal. Para obter mais informações sobre quais os tipos podem ser especificados com os sufixos de letra, consulte as páginas de referência para os tipos individuais em Value Types (C# Reference).

Porque os literais são digitadas e todos os tipos derivam essencialmente de System.Object, você pode escrever e compilar o código, como a seguir:

string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);

Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);

Tipos genéricos

Um tipo pode ser declarado com um ou mais parâmetros de tipo que servem como um espaço reservado para o tipo real (o tipo concreto) que o código de cliente fornecerá quando ele cria uma instância do tipo. Esses tipos são chamados de tipos genéricos. Por exemplo, o.Tipo do NET Framework System.Collections.Generic.List<T> tem um parâmetro de tipo, que por convenção é dado o nome t. Quando você cria uma instância do tipo, você pode especificar o tipo dos objetos que a lista conterá, por exemplo, a seqüência de caracteres:

List<string> strings = new List<string>();

O uso do parâmetro de tipo torna possível reutilizar a mesma classe para conter qualquer tipo de elemento, sem precisar converter cada elemento a ser objeto. São chamados de classes de coleção genérica coleções com rigidez de tipos porque o compilador sabe o tipo específico dos elementos da coleção e pode elevar um erro em tempo de compilação se, por exemplo, tentar adicionar um número inteiro para o strings o objeto no exemplo anterior. Para obter mais informações, consulte Generics (C# Programming Guide).

Tipos implícitos, tipos anônimos e tipos anuláveis

Conforme mencionado anteriormente, você implicitamente pode digitar uma variável local (mas não os membros de classe) usando o var palavra-chave. A variável ainda recebe um tipo em tempo de compilação, mas o tipo é fornecido pelo compilador. Para obter mais informações, consulte Implicitamente digitado variáveis locais (C# guia de programação).

Em alguns casos, é inconveniente criar um tipo nomeado para conjuntos simples de valores relacionados que você não pretende armazenar ou passar fora dos limites de método. Você pode criar tipos anônimos para essa finalidade. Para obter mais informações, consulte Tipos anônimos (guia de programação de C#).

Tipos comuns de valor não podem ter um valor de Nulo. No entanto, você pode criar tipos de valor anulável fixar uma ? após o tipo. Por exemplo, int? é um int que também pode ter o valor do tipo Nulo. No CTS, tipos anuláveis são instâncias do tipo struct genérico System.Nullable<T>. Tipos anuláveis são especialmente úteis quando você está passando dados para e de bancos de dados no qual os valores numéricos podem ser nulos. Para obter mais informações, consulte Nullable Types (C# Programming Guide).

Seções relacionadas

Para obter mais informações, consulte os seguintes tópicos:

Especificação da linguagem C#

Para obter mais informações, consulte C# Language Specification A especificação de linguagem é a fonte definitiva para a sintaxe e o uso de C#.

Consulte também

Referência

Tipos de dados comparados em vários idiomas

Integral Types Table (C# Reference)

Conceitos

C# Programming Guide

Conversion of XML Data Types

Outros recursos

C# Reference