Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Определение класса или структуры похоже на схему, указывающую, что может сделать тип. Объект в основном является блоком памяти, который был выделен и настроен в соответствии с схемой. Программа может создавать множество объектов одного класса. Объекты также называются экземплярами, и они могут храниться либо в именованной переменной, либо в массиве или коллекции. Клиентский код — это код, который использует эти переменные для вызова методов и доступа к общедоступным свойствам объекта. В объектно-ориентированном языке, например C#, типичная программа состоит из нескольких объектов, взаимодействующих динамически.
Примечание.
Статические типы ведут себя не так, как описано здесь. Дополнительные сведения см. в статье Статические классы и члены статических классов.
Экземпляры структур против экземпляров классов
Поскольку классы являются ссылочными типами, переменная объекта класса содержит ссылку на адрес объекта в управляемой куче. Если для первой переменной назначена вторая переменная одного типа, обе переменные ссылаются на объект по указанному адресу. Эта точка подробно рассматривается далее в этой статье.
Экземпляры классов создаются с помощью new
оператора. В следующем примере Person
тип и person1
person2
являются экземплярами или объектами этого типа.
using System;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
// Other properties, methods, events...
}
class Program
{
static void Main()
{
Person person1 = new Person("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
*/
Поскольку структуры являются типами значений, переменная объекта структуры содержит копию всего объекта. Экземпляры структур также можно создать с помощью new
оператора, но это не обязательно, как показано в следующем примере:
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 Person("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
*/
}
Память для обоих p1
и p2
выделяется в стеке потоков. Эта память освобождается вместе с типом данных или методом, в котором она объявлена. Это одна из причин, по которой структуры копируются при присваивании. В отличие от этого, память, выделенная для экземпляра класса, автоматически удаляется (сборка мусора) средой CLR, когда все ссылки на объект вышли из области. Детерминированно уничтожить объект класса, как в C++, невозможно. Дополнительные сведения о сборке мусора в .NET см. в статье "Сборка мусора".
Примечание.
Выделение и распределение памяти в управляемой куче оптимизировано в среде CLR. В большинстве случаев нет существенной разницы в производительности выделения экземпляра класса в куче и выделения экземпляра структуры в стеке.
Удостоверение объекта и равенство значений
При сравнении двух объектов для равенства необходимо сначала определить, представляют ли две переменные один и тот же объект в памяти или совпадают ли значения одного или нескольких полей. Если вы собираетесь сравнить значения, необходимо учитывать, являются ли объекты экземплярами типов значений (структур) или ссылочных типов (классов, делегатов, массивов).
Чтобы определить, относятся ли два экземпляра класса к одному расположению в памяти (что означает, что они имеют одно и то же удостоверение), используйте статический Object.Equals метод. (System.Object является неявным базовым классом для всех типов значений и ссылочных типов, включая определяемые пользователем структуры и классы.)
Чтобы определить, имеют ли поля экземпляра в двух экземплярах структуры одинаковые значения, используйте ValueType.Equals метод. Так как все структуры неявно наследуются System.ValueType, метод вызывается непосредственно в объекте, как показано в следующем примере:
// Person is defined in the previous example. //public struct Person //{ // public string Name; // public int Age; // public Person(string name, int age) // { // Name = name; // Age = age; // } //} Person p1 = new Person("Wallace", 75); Person p2 = new Person("", 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.
Реализация System.ValueType в
Equals
использует упаковку и рефлексию в некоторых случаях. Сведения о том, как предоставить эффективный алгоритм равенства, специфичный для вашего типа, смотрите в статье Определение равенства значений для типа. Записи — это ссылочные типы, которые используют семантику значений для определения равенства.Чтобы определить, равны ли значения полей в двух экземплярах класса, можно использовать Equals метод или оператор == . Однако используйте их только в том случае, если класс переопределяет или перегружает их, чтобы предоставить пользовательское определение того, что означает "равенство" для объектов этого типа. Класс также может реализовать IEquatable<T> интерфейс или IEqualityComparer<T> интерфейс. Оба интерфейса предоставляют методы, которые можно использовать для проверки равенства значений. При проектировании собственных классов, которые переопределяют
Equals
, обязательно следуйте рекомендациям, изложенным в разделе «Как определить равенство значений для типа» и Object.Equals(Object).
Связанные разделы
Дополнительные сведения: