Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Uma definição de classe ou struct é como um blueprint 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. Você também pode chamar instâncias de objetos. Você pode armazená-los em uma variável nomeada ou em uma matriz ou coleção. O código do cliente usa essas variáveis para chamar os métodos e acessar as 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 se comportam de forma diferente do descrito neste artigo. Para obter mais informações, consulte Classes estáticas e membros de classe estática.
Instâncias de struct vs. instâncias de class
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 você atribuir uma segunda variável do mesmo tipo à primeira variável, ambas as variáveis se referirão ao objeto nesse endereço. Este artigo aborda esse ponto mais detalhadamente mais tarde.
Você cria instâncias de classes usando o new operador. 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 os structs são tipos de valor, uma variável de um objeto struct contém uma cópia de todo o objeto. Você também pode criar instâncias de structs usando o new operador, mas não precisa usá-lo, conforme mostrado no exemplo a seguir:
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 de thread aloca memória para ambos p1 e p2. O programa recupera essa memória junto com o tipo ou método no qual você a declara. Esse gerenciamento de memória é um dos motivos pelos quais os structs são copiados ao serem atribuídos. Por outro lado, o common language runtime recupera automaticamente (coleta lixo) a memória alocada para uma instância de classe quando todas as referências ao objeto saem do escopo. Você não pode destruir deterministicamente um objeto de classe como você pode no C++. Para obter mais informações sobre a coleta de lixo no .NET, consulte Coleta de Lixo.
Observação
O Common Language Runtime otimiza significativamente a alocação e a liberação de memória no heap gerenciado. Na maioria dos casos, não há diferença significativa no custo de desempenho ao alocar uma instância de classe no heap versus alocar uma instância de struct na pilha.
Identidade do objeto versus igualdade de valor
Ao comparar dois objetos para igualdade, primeiro decida se deseja saber se as duas variáveis representam o mesmo objeto na memória ou se os valores de um ou mais de seus campos são equivalentes. Se você quiser comparar valores, considere se os objetos são instâncias de tipos de valor (structs) ou tipos de referência (classes, delegados, matrizes).
Use o método estático Object.ReferenceEquals para determinar se duas instâncias de classe se referem ao mesmo local na memória (o que significa que elas têm a mesma identidade). (System.Object é a classe base implícita para todos os tipos de valor e tipos de referência, incluindo structs e classes definidos pelo usuário.)
Por padrão, o ValueType.Equals método determina se os campos de instância em duas instâncias de struct têm os mesmos valores. Como todos os structs herdam implicitamente de 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 boxing e reflection em alguns casos. Para obter informações sobre como fornecer um algoritmo de igualdade eficiente específico ao seu tipo, consulte Implementar a igualdade por conta própria quando um tipo não pode ser um registro. 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ê pode 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 valor. Ao projetar suas próprias classes que substituem
Equals, siga as diretrizes declaradas em Implementar igualdade quando um tipo não puder ser um registro e Object.Equals(Object).
Seções relacionadas
Para obter mais informações, consulte: