Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Uma definição de classe ou struct é como um esquema que especifica o que o tipo pode fazer. Um objeto é um bloco de memória que o programa aloca e configura de acordo com o blueprint. Um programa pode criar muitos objetos da mesma classe. Também se pode chamar instâncias aos objetos. Pode armazená-los numa variável nomeada ou num array ou coleção. O código cliente utiliza estas variáveis para chamar os métodos e aceder às propriedades públicas do objeto. Em uma linguagem orientada a objetos como C#, um programa típico consiste em vários objetos interagindo dinamicamente.
Observação
Os tipos estáticos comportam-se de forma diferente do que é descrito neste artigo. Para obter mais informações, consulte Classes estáticas e membros de classes estáticas.
Instâncias de structs versus instâncias de classes
Como as classes são tipos de referência, uma variável de um objeto de classe contém uma referência ao endereço do objeto no heap gerenciado. Se atribuir uma segunda variável do mesmo tipo à primeira variável, ambas as variáveis referem-se ao objeto nesse endereço. Este artigo aborda este ponto com mais detalhe mais adiante.
Criam-se instâncias de classes utilizando o operador new. No exemplo a seguir, Person é o tipo e person1 e person2 são instâncias, ou objetos, desse tipo.
using System;
public class Person(string name, int age)
{
public string Name { get; set; } = name;
public int Age { get; set; } = age;
// Other properties, methods, events...
}
class Program
{
static void Main()
{
Person person1 = new("Leopold", 6);
Console.WriteLine($"person1 Name = {person1.Name} Age = {person1.Age}");
// Declare new person, assign person1 to it.
Person person2 = person1;
// Change the name of person2, and person1 also changes.
person2.Name = "Molly";
person2.Age = 16;
Console.WriteLine($"person2 Name = {person2.Name} Age = {person2.Age}");
Console.WriteLine($"person1 Name = {person1.Name} Age = {person1.Age}");
/*
Output:
person1 Name = Leopold Age = 6
person2 Name = Molly Age = 16
person1 Name = Molly Age = 16
*/
}
}
Como structs são tipos de valor, uma variável de um objeto struct contém uma cópia do objeto inteiro. Também pode criar instâncias de structs usando o new operador, mas não precisa de o usar, como mostrado no exemplo seguinte:
using System;
namespace Example
{
public struct Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
public class Application
{
static void Main()
{
// Create struct instance and initialize by using "new".
// Memory is allocated on thread stack.
Person p1 = new("Alex", 9);
Console.WriteLine($"p1 Name = {p1.Name} Age = {p1.Age}");
// Create new struct object. Note that struct can be initialized
// without using "new".
Person p2 = p1;
// Assign values to p2 members.
p2.Name = "Spencer";
p2.Age = 7;
Console.WriteLine($"p2 Name = {p2.Name} Age = {p2.Age}");
// p1 values remain unchanged because p2 is copy.
Console.WriteLine($"p1 Name = {p1.Name} Age = {p1.Age}");
}
}
/*
Output:
p1 Name = Alex Age = 9
p2 Name = Spencer Age = 7
p1 Name = Alex Age = 9
*/
}
A pilha da thread aloca memória tanto para p1 como para p2. O programa recupera essa memória juntamente com o tipo ou método em que a declaras. Esta gestão de memória é uma das razões pelas quais as estruturas são copiadas na atribuição. Em contraste, o runtime da linguagem comum recupera automaticamente (recolhe lixo) a memória que aloca para uma instância de classe quando todas as referências ao objeto saem do âmbito. Não podes destruir deterministicamente um objeto de classe como podes em C++. Para obter mais informações sobre a coleta de lixo no .NET, consulte Coleta de lixo.
Observação
O tempo de execução da linguagem comum otimiza altamente a alocação e deslocação de memória no heap gerido. Na maioria dos casos, não há diferença significativa no custo de desempenho da alocação de uma instância de classe no heap versus a alocação de uma instância struct na pilha.
Identidade do objeto vs. igualdade de valores
Quando compara dois objetos para igualdade, decida primeiro se quer saber se as duas variáveis representam o mesmo objeto na memória ou se os valores de um ou mais dos seus campos são equivalentes. Se quiser comparar valores, considere se os objetos são instâncias de tipos de valor (structs) ou tipos de referência (classes, delegados, arrays).
Use o método estático Object.ReferenceEquals para determinar se duas instâncias de classe se referem à mesma localização na memória (o que significa que têm a mesma identidade). System.Object( é a classe base implícita para todos os tipos de valor e tipos de referência, incluindo estruturas e classes definidas pelo usuário.)
Por defeito, o método ValueType.Equals determina se os campos de instância de duas instâncias de estrutura têm os mesmos valores. Como todas as estruturas herdam implicitamente do System.ValueType, você chama o método diretamente em seu objeto, conforme mostrado no exemplo a seguir:
// Person is defined in the previous example. //public struct Person(string name, int age) //{ // public string Name { get; set; } = name; // public int Age { get; set; } = age; //} Person p1 = new("Wallace", 75); Person p2 = new("", 42); p2.Name = "Wallace"; p2.Age = 75; if (p2.Equals(p1)) Console.WriteLine("p2 and p1 have the same values."); // Output: p2 and p1 have the same values.A implementação padrão System.ValueType de
Equalsusa caixotagem e reflexão em alguns casos. Para informações sobre como fornecer um algoritmo de igualdade eficiente e específico para o seu tipo, veja Implementar igualdade por si próprio quando um tipo não pode ser um registo. Os registros são tipos de referência que usam semântica de valor para igualdade.Para determinar se os valores dos campos em duas instâncias de classe são iguais, você poderá usar o Equals método ou o operador == . No entanto, use-os apenas se a classe os tiver substituído ou sobrecarregado para fornecer uma definição personalizada do que "igualdade" significa para objetos desse tipo. A classe também pode implementar a IEquatable<T> interface ou a IEqualityComparer<T> interface. Ambas as interfaces fornecem métodos que podem ser usados para testar a igualdade de valores. Ao desenhar as suas próprias classes que se sobrepõem
Equals, certifique-se de seguir as diretrizes indicadas em Implemente a igualdade por si próprio quando um tipo não pode ser um registo e Object.Equals(Object).
Secções relacionadas
Para obter mais informações, consulte: