В .NET есть две категории типов: ссылочные типы и типы значений .
Структуры являются типами значений, а классы являются ссылочными типами .
Общее отличие состоит в том, что ссылочный тип живет в куче, а тип значения живет встроенным, то есть везде, где определена ваша переменная или поле.
Переменная, содержащая тип значения, содержит полное значение типа значения. Для структуры это означает, что переменная содержит всю структуру со всеми ее полями.
Переменная, содержащая ссылочный тип, содержит указатель или ссылку на другое место в памяти, где находится фактическое значение.
Это имеет одно преимущество, для начала:
- типы значений всегда содержат значение
- ссылочные типы могут содержать нулевую ссылку, то есть в данный момент они вообще ни на что не ссылаются
Внутренне ссылочные типы s реализованы как указатели, и, зная это и зная, как работает присвоение переменной, существуют другие поведенческие паттерны:
- копируя содержимое переменной типа значения в другую переменную, копирует все содержимое в новую переменную, выделяя две разные. Другими словами, после копирования изменения одного не повлияют на другое
- копируя содержимое переменной ссылочного типа в другую переменную, копирует ссылку, что означает, что теперь у вас есть две ссылки на одно и то же другое хранилище фактических данных. Другими словами, после копирования изменение данных в одной ссылке также повлияет на другую, но только потому, что вы действительно просто просматриваете одни и те же данные в обоих местах.
Когда вы объявляете переменные или поля, вот как эти два типа различаются:
- переменная: тип значения живет в стеке, ссылочный тип живет в стеке как указатель на место где-то в динамической памяти, где живет реальная память (хотя обратите внимание на серию статей Эрика Липпертса: «Стек - деталь реализации» ).
- class / struct-field: тип значения живет полностью внутри типа, ссылочный тип живет внутри типа как указатель на место в кучной памяти, где живет реальная память.
Лассе В. Карлсен
источник
Краткое резюме каждого:
Только классы:
Только структуры:
Классы и структуры:
источник
c# struct memory overhead
и нашел ответ Ханса Пассанта, который говорит, что нет, это тоже не так. Так что же вы имеете в виду?class
являются управляемой памятью (обрабатывается сборщиком мусора), тогда как экземплярыstruct
не являются ,В .NET объявления структуры и класса различают ссылочные типы и типы значений.
Когда вы передаете тип ссылки, на самом деле сохраняется только один. Весь код, который обращается к экземпляру, обращается к одному и тому же.
Когда вы передаете тип значения, каждый из них является копией. Весь код работает над собственной копией.
Это можно показать на примере:
Для класса это было бы иначе
Классы могут быть ничем - ссылка может указывать на ноль.
Структуры являются фактическим значением - они могут быть пустыми, но никогда не равными нулю. По этой причине структуры всегда имеют конструктор по умолчанию без параметров - им нужно «начальное значение».
источник
Разница между структурами и классами:
источник
От выбора Microsoft между классом и структурой ...
источник
Помимо всех отличий, описанных в других ответах:
Если вы после видео, объясняющего все различия, вы можете проверить Часть 29 - Учебник по C # - Различия между классами и структурами в C # .
источник
Экземпляры классов хранятся в управляемой куче. Все переменные, «содержащие» экземпляр, являются просто ссылкой на экземпляр в куче. Передача объекта в метод приводит к тому, что передается копия ссылки, а не сам объект.
Структуры (технически, типы значений) хранятся везде, где они используются, во многом как примитивный тип. Содержимое может быть скопировано средой выполнения в любое время и без вызова настроенного конструктора копирования. Передача типа значения в метод включает копирование всего значения, опять же, без вызова какого-либо настраиваемого кода.
Различия лучше сделаны именами C ++ / CLI: «ref class» - это класс, который описан первым, «value class» - это класс, который описан вторым. Ключевые слова «класс» и «структура», используемые в C #, - это просто то, что нужно усвоить.
источник
источник
Структура против класса
Структура является типом значения, поэтому она хранится в стеке, но класс является ссылочным типом и хранится в куче.
Структура не поддерживает наследование и полиморфизм, но класс поддерживает оба.
По умолчанию все члены структуры являются открытыми, но члены класса по умолчанию являются закрытыми по своей природе.
Поскольку структура является типом значения, мы не можем присвоить null объекту struct, но это не относится к классу.
источник
Чтобы добавить к другим ответам, есть одно фундаментальное различие, которое стоит отметить, и это то, как данные хранятся в массивах, так как это может существенно повлиять на производительность.
Таким образом, массив структур выглядит так в памяти
[struct][struct][struct][struct][struct][struct][struct][struct]
В то время как массив классов выглядит следующим образом
[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]
С массивом классов интересующие вас значения хранятся не в массиве, а в другом месте в памяти.
Для подавляющего большинства приложений это различие не имеет большого значения, однако в высокопроизводительном коде это повлияет на локальность данных в памяти и окажет большое влияние на производительность кэша ЦП. Использование классов, когда вы могли / должны были использовать структуры, значительно увеличит количество кеш-пропусков в процессоре.
Самым медленным, что делает современный ЦП, является не сокращение чисел, а извлечение данных из памяти, а попадание в кэш L1 во много раз быстрее, чем чтение данных из ОЗУ.
Вот код, который вы можете проверить. На моей машине перебор массива классов занимает в 3 раза больше времени, чем массив struct.
источник
Просто чтобы сделать его завершенным, при использовании
Equals
метода есть еще одно отличие , которое наследуется всеми классами и структурами.Допустим, у нас есть класс и структура:
и в методе Main у нас есть 4 объекта.
Затем:
Таким образом , структуры подходят для подобных объектам чисел, таких как точки (сохраните координаты x и y). И занятия подходят для других. Даже если 2 человека имеют одинаковое имя, рост, вес ..., они все равно 2 человека.
источник
Ну, для начала, структура передается по значению, а не по ссылке. Структуры хороши для относительно простых структур данных, в то время как классы обладают гораздо большей гибкостью с архитектурной точки зрения благодаря полиморфизму и наследованию.
Другие, вероятно, могут дать вам больше деталей, чем я, но я использую структуры, когда структура, к которой я иду, проста.
источник
Помимо основных различий в спецификаторе доступа и нескольких упомянутых выше, я хотел бы добавить некоторые из основных отличий, включая несколько упомянутых выше, с примером кода с выводом, который даст более четкое представление о ссылке и значении
Структуры:
Учебный класс:
Пример кода
Вывод
Начальное значение объекта Struct: 10
Метод Inside Struct Значение метода Inside объекта Struct: 20
После вызова метода значение объекта Struct: 10
Начальное значение Class Object: 10
Метод внутри класса Значение метода внутри объекта Class: 20
После вызова метода значение объекта класса: 20
Здесь вы можете ясно увидеть разницу между вызовом по значению и вызовом по ссылке.
источник
Для событий, объявленных в классе, их доступ + = и - = автоматически блокируется через блокировку (это), чтобы сделать их потокобезопасными (статические события блокируются для типа класса). События, объявленные в структуре, не имеют автоматически заблокированных доступа + = и - =. Блокировка (это) для структуры не будет работать, так как вы можете заблокировать только выражение ссылочного типа.
Создание экземпляра структуры не может вызвать сборку мусора (если конструктор прямо или косвенно не создает экземпляр ссылочного типа), тогда как создание экземпляра ссылочного типа может вызвать сборку мусора.
Структура всегда имеет встроенный открытый конструктор по умолчанию.
Это означает, что структура всегда является экземпляром, тогда как класс может не существовать, поскольку все его конструкторы могут быть закрытыми.
Структура не может иметь деструктора. Деструктор - это просто переопределение объекта. Финализованное скрытие, и структуры, являющиеся типами значений, не подлежат сборке мусора.
Структура неявно запечатана, а класс - нет.
Структура не может быть абстрактной, класс может.
Структура не может вызвать: base () в своем конструкторе, тогда как класс без явного базового класса может.
Структура не может расширять другой класс, класс может.
Структура не может объявлять защищенные члены (например, поля, вложенные типы), которые может сделать класс.
Структура не может объявлять абстрактные функции-члены, абстрактный класс может.
Структура не может объявлять члены виртуальной функции, класс может.
Структура не может объявлять запечатанные члены функции, класс может.
Структура не может объявлять переопределение членов функции, класс может.
Единственным исключением из этого правила является то, что структура может переопределять виртуальные методы System.Object, viz, Equals () и GetHashCode () и ToString ().
источник
Object
, которыйКак уже упоминалось ранее: классы являются ссылочным типом, в то время как структуры являются типами значений со всеми вытекающими последствиями.
Как правило, Framework Design Guidelines рекомендует использовать Structs вместо классов, если:
источник
Есть один интересный случай головоломки «класс против структуры» - ситуация, когда вам нужно вернуть несколько результатов из метода: выбрать, какой использовать. Если вы знаете историю ValueTuple - вы знаете, что ValueTuple (структура) был добавлен, потому что он должен быть более эффективным, чем Tuple (класс). Но что это значит в цифрах? Два теста: один - это struct / class, который имеет 2 поля, другой - с struct / class, который имеет 8 полей (с размерностью более 4 - класс должен стать более эффективным, чем struct с точки зрения тактов процессора, но, конечно, следует учитывать и загрузку GC ).
PS Еще один тест для конкретного случая «sturct или class with collection»: https://stackoverflow.com/a/45276657/506147
Тест кода:
источник
Это правда, однако следует также отметить, что с .NET 2 структуры поддерживают Nullable-версию, а C # предоставляет некоторый синтаксический сахар для упрощения использования.
источник
(object)(default(int?)) == null
что вы не можете делать с любым другим типом значения, потому что здесь происходит нечто большее, чем просто сахар. Единственный сахарint?
дляNullable<int>
.Каждая переменная или поле типа примитивного значения или типа структуры содержит уникальный экземпляр этого типа, включая все его поля (публичные и приватные). Напротив, переменные или поля ссылочных типов могут иметь значение null или могут ссылаться на объект, хранящийся в другом месте, на который также может существовать любое количество других ссылок. Поля структуры будут храниться в том же месте, что и переменная или поле этого типа структуры, которые могут находиться либо в стеке, либо частью другого объекта кучи.
Создание переменной или поля типа примитивного значения создаст его со значением по умолчанию; Создание переменной или поля типа структуры создаст новый экземпляр, создавая все поля в нем способом по умолчанию. Создание нового экземпляра ссылочного типа начнется с создания всех полей в нем по умолчанию, а затем запускается необязательный дополнительный код в зависимости от типа.
Копирование одной переменной или поля типа примитива в другое приведет к копированию значения. Копирование одной переменной или поля типа структуры в другое приведет к копированию всех полей (открытых и закрытых) первого экземпляра во второй. Копирование одной переменной или поля ссылочного типа в другое приведет к тому, что последняя будет ссылаться на тот же экземпляр, что и первый (если есть).
Важно отметить, что в некоторых языках, таких как C ++, семантическое поведение типа не зависит от того, как он хранится, но это не относится к .NET. Если тип реализует семантику изменяемых значений, копирование одной переменной этого типа в другую копирует свойства первого экземпляра в другой, на который ссылается второй, и использование элемента второго для его изменения приведет к изменению этого второго экземпляра. , но не первый. Если тип реализует изменяемую ссылочную семантику, копирование одной переменной в другую и использование элемента второй для изменения объекта будет влиять на объект, на который ссылается первая переменная; типы с неизменяемой семантикой не допускают мутации, поэтому семантически не имеет значения, создает ли копирование новый экземпляр или создает другую ссылку на первый.
В .NET типы значений могут реализовывать любую из вышеуказанных семантик при условии, что все их поля могут действовать аналогичным образом. Однако ссылочный тип может реализовывать только изменяемую ссылочную семантику или неизменяемую семантику; Типы значений с полями изменяемых ссылочных типов ограничены либо реализацией изменяемой ссылочной семантики, либо странной гибридной семантикой.
источник