структуры в C
Это совокупность нескольких переменных, часто различных типов, сгруппированных под единым именем для удобства обращения. Главное изменение, внесённое стандартом ANSI в работу со структурами, — это определение присваивания структур. Теперь структуры можно копировать, присваивать, передавать в функции и возвращать из функций.
Ключевое слово struct начинает объявление структуры, состоящее из списка объявлений элементов в фигурных скобках. После слова struct может стоять необязательный идентификатор, именуемый меткой структуры. Метка обозначает конкретный структурный тип; впоследствии её можно использовать для краткости, опуская всё, что находится в скобках при объявлении структур того же типа.
Переменные, перечисленные в объявлении структуры, называются её членами, элементами или полями. Элемент структуры или её метка может иметь то же имя, что и обыкновенная переменная безо всякого конфликта, поскольку они всегда отличаются по контексту.
Объявление со словом struct фактически вводит новый тип данных. Поэтому допустимо такое объявление переменных:
Данный код объявляет переменные \(x, y, z\) определённого именованного типа и выделяет для них место в памяти. Объявление структуры, после которого нет списка переменных, не выделяет никакой памяти для объектов, а просто описывает форму структуры. Так же можно объявлять переменные, используя метку структуры:
Структуру можно инициализировать, поставив после её определения список значений-констант:
Обращение к элементам структуры выполняется следующим образом:
Структуры можно вкладывать друг в друга:
1.1 Структуры и функции
Расширенными операциями над структурами являются копирование или присваивание структуры как целого, взятие её адреса операцией &, а так же обращение к её элементам. Копирование и присваивание включают также в себя передачу аргументов в функции и возвращение значений из функций. Структуры нельзя сравнивать между собой. Структуру можно инициализировать списком констант-инициализаторов для всех её полей.
Вместо того чтобы помещать результат во временную переменную, мы инкрементировали компоненты структуры p1, чтобы подчеркнуть тот факт, что параметры-структуры передаются по значениям, как и любые другие параметры.
Если в функцию необходимо передать большую структуру, это лучше сделать передав указатель на неё, а не копию всех её данных. Указатели на структуры обладают всеми свойстваи указателей на обычные переменные.
Указатели на структуры используются так часто, что для удобства записи ссылок по ним введено дополнительное обозначение: p->элемент-структуры
Структуры

Как вам должно быть уже известно, классы относятся к ссылочным типам данных. Это означает, что объекты конкретного класса доступны по ссылке, в отличие от значений простых типов, доступных непосредственно. Но иногда прямой доступ к объектам как к значениям простых типов оказывается полезно иметь, например, ради повышения эффективности программы. Ведь каждый доступ к объектам (даже самым мелким) по ссылке связан с дополнительными издержками на расход вычислительных ресурсов и оперативной памяти.
Для разрешения подобных затруднений в C# предусмотрена структура, которая подобна классу, но относится к типу значения, а не к ссылочному типу данных. Т.е. структуры отличаются от классов тем, как они сохраняются в памяти и как к ним осуществляется доступ (классы — это ссылочные типы, размещаемые в куче, структуры — типы значений, размещаемые в стеке), а также некоторыми свойствами (например, структуры не поддерживают наследование). Из соображений производительности вы будете использовать структуры для небольших типов данных. Однако в отношении синтаксиса структуры очень похожи на классы.
Главное отличие состоит в том, что при их объявлении используется ключевое слово struct вместо class. Ниже приведена общая форма объявления структуры:
где имя обозначает конкретное имя структуры.
Как и у классов, у каждой структуры имеются свои члены: методы, поля, индексаторы, свойства, операторные методы и события. В структурах допускается также определять конструкторы, но не деструкторы. В то же время для структуры нельзя определить конструктор, используемый по умолчанию (т.е. конструктор без параметров). Дело в том, что конструктор, вызываемый по умолчанию, определяется для всех структур автоматически и не подлежит изменению. Такой конструктор инициализирует поля структуры значениями, задаваемыми по умолчанию. А поскольку структуры не поддерживают наследование, то их члены нельзя указывать как abstract, virtual или protected.
Объект структуры может быть создан с помощью оператора new таким же образом, как и объект класса, но в этом нет особой необходимости. Ведь когда используется оператор new, то вызывается конструктор, используемый по умолчанию. А когда этот оператор не используется, объект по-прежнему создается, хотя и не инициализируется. В этом случае инициализацию любых членов структуры придется выполнить вручную.
Давайте рассмотрим пример использования структур:

Обратите внимание, когда одна структура присваивается другой, создается копия ее объекта. В этом заключается одно из главных отличий структуры от класса. Когда ссылка на один класс присваивается ссылке на другой класс, в итоге ссылка в левой части оператора присваивания указывает на тот же самый объект, что и ссылка в правой его части. А когда переменная одной структуры присваивается переменной другой структуры, создается копия объекта структуры из правой части оператора присваивания.
Поэтому, если бы в предыдущем примере использовался класс UserInfo вместо структуры, получился бы следующий результат:

Назначение структур
В связи с изложенным выше возникает резонный вопрос: зачем в C# включена структура, если она обладает более скромными возможностями, чем класс? Ответ на этот вопрос заключается в повышении эффективности и производительности программ. Структуры относятся к типам значений, и поэтому ими можно оперировать непосредственно, а не по ссылке. Следовательно, для работы со структурой вообще не требуется переменная ссылочного типа, а это означает в ряде случаев существенную экономию оперативной памяти.
Более того, работа со структурой не приводит к ухудшению производительности, столь характерному для обращения к объекту класса. Ведь доступ к структуре осуществляется непосредственно, а к объектам — по ссылке, поскольку классы относятся к данным ссылочного типа. Косвенный характер доступа к объектам подразумевает дополнительные издержки вычислительных ресурсов на каждый такой доступ, тогда как обращение к структурам не влечет за собой подобные издержки. И вообще, если нужно просто сохранить группу связанных вместе данных, не требующих наследования и обращения по ссылке, то с точки зрения производительности для них лучше выбрать структуру.
Любопытно, что в С++ также имеются структуры и используется ключевое слово struct. Но эти структуры отличаются от тех, что имеются в C#. Так, в С++ структура относится к типу класса, а значит, структура и класс в этом языке практически равноценны и отличаются друг от друга лишь доступом по умолчанию к их членам, которые оказываются закрытыми для класса и открытыми для структуры. А в C# структура относится к типу значения, тогда как класс — к ссылочному типу.
Структуры в C# и ее плюсы
Где можно использовать структуры? И в каких ситуациях лучше прибегнуть к структурам, нежели к классам?
Это довольно интересный вопрос.
С одной стороны, структуры в C# есть. Но они очень похожи на классы: у них тоже есть конструкторы — деструкторы, методы. Не надо заботиться об инициализации полей структур — .NET не забудет это сделать.
Единственная разница, которая приходит в голову — что поля структуры нельзя инициализировать в момент объявления.
И что при создании экземпляра структуры new не нужен, достаточно простого объявления вида
Главное отличие структур от классов — в реализации. Любой экземпляр класса создаётся в "куче" (heap) (потому, что класс — это ссылочная структура данных), а экземпляры структур создаются в стеке, как простые переменные примитивных типов.
Это приводит к тому, что активное создание — освобождение экземпляров классов даст работу garbage collector, а экземпляров структур — нет. В целом, счтруктуры нужны там, где производительность на первом месте, и данных "не очень много".
Некоторые преимущества структур, которые проявлялись в C/C++: можно было напрямую записывать "набор байтов длииной со структуру" в бинарный файл — и это было сохранение значения структуры в файле! безо всяких сериализаций. А потом точно такое же считывание. Или — передача по сети.
В комментариях мне подсказывают, что такие же возможности есть и в C#, но использовать их сложнее, чем в C++.
Если я найду примеры такого использования — я постараюсь дополнить этот ответ.
Структуры (struct) в C#
Структура ( struct ) в C# — это пользовательский тип данных, который используется наряду с классами и может содержать какие-либо данные и методы. Структурами также являются такие типы данных как int , double и т.д. Основное отличие структуры ( struct ) от класса ( class ) заключается в том, что структура — это тип значений, а класс — это ссылочный тип.
Объявление структуры
Для того, чтобы объявить переменную типа структуры в C# используется ключевое слово struct :
После ключевого слова struct следует имя структуры и далее, в фигурных скобках — элементы структуры (поля, методы и т.д.). Например, определим структуру, которая описывает точку в трехмерном пространстве:
Наша структура содержит три свойства — координаты X,Y,Z и один переопределенный метод ToString , который возвращает строку с координатами точки. Обращение к полям, свойствам и методам структуры, как и в случае с классами, происходит с использованием имени переменной, например:
здесь Point — это имя переменной типа Point3D .
Создание структуры
Как и в случае с классами, структуры в C# можно создавать с использованием ключевого слова new :
После того, как структура создана, её полям и свойствам можно присваивать значения (см. в предыдущем пункте).
Начиная с .NET 5 в C# 9 можно использовать краткую форму записи new :
Если структура содержит только публичные поля (не путать со свойствами) и методы, то можно не вызывать конструктор, а сразу назначить значение полей и после этого вызывать методы структуру. Например:
Начиная с версии C# 10 полям структуры можно присваивать значения по умолчанию, однако, в этом случае необходимо будет вызвать new(), чтобы создать экземпляр структуры. Например:
Если мы попытаемся вывести в консоль значения полей вот так:
то получим ошибку «Попытка доступа к неинициализированной переменной». Поэтому, необходимо получать доступ к переменной point с использованием оператора new:
Конструкторы структур
Здесь, опять же, структуры ничем не отличаются от классов C#. У любой структуры есть как минимум один конструктор (конструктор по умолчанию) без параметров. При этом, мы можем создавать свои конструкторы и точно также, как и с классами вызывать их по цепочке, например:
Создаем структуры ( struct )
Начиная с версии C# 10 мы можем также создать для структуры свой конструктор без параметров:
Инициализатор структур struct
Значения полей и свойств структуры, как в случае и с классами, можно задавать непосредственно при создании, используя следующую языковую конструкцию:
то есть вначале мы объявляем переменную, затем вызываем конструктор и затем в фигурных скобках указываем имена полей или свойств и их значения. Даже, если мы создадим и проинициализируем структуру вот так:
то значения полей будут теми, которые мы указываем в инициализаторе, т.е. 24, 45 и 22.
Копирование структур с изменением значений (оператор with)
Начиная с версии C# 10 мы можем копировать значения структур с изменениями, например:
Вывод в консоли:
Отличие структуры от класса в C#
Думаю, что после прочтения всего, что было выше, у любого начинающего программировать в C# человека возникнет резонный вопрос: если у структур в C# всё тоже самое, что и у классов. то зачем нам эти структуры нужны и, если всё-таки они нужны, то когда их использовать? Попробуем в кратце разобраться с этим вопросом вместе.
Структура — тип значений, класс — ссылочный тип
Если не вдаваться далеко в подробности работы программ, то основное отличие struct от class заключается в том, что структура храниться целиком в стеке, а объект класса храниться в куче, а ссылка на него — в стеке. В результате этого, доступ к данным структуре будет путь не намного, но быстрее, чем к классу. О том, что такое стек и куча мы ещё поговорим позднее.
Структуры не поддерживают наследование
В отличие от классов C#, наследование структур не поддерживается, то есть вот такой код приведет к ошибке:
Когда использовать структуры (struct), а когда классы (class) в C#
Конечно, вопрос о том, что лучше использовать зависит, в первую очередь, от того в контексте чего задается такой вопрос, но основная рекомендация от Microsoft может быть сформулирована следующим образом: структуры (struct) стоит использовать в том случае, если ваш объект содержит минимальное количество каких-либо логически связанных операций или не содержит их вообще.
Например, использование структур вполне оправдано в примерах выше — описание точки в трехмерном пространстве. Максимум логики, которую мы можем добавить в структуру — это переопределить операторы сложения, вычитания и равенства.
Если же мы пробуем описать с помощью своего типа данных, например, автомобиль, то тут уже логика может быть самая разветвленная: проверка наличия топлива в баке, технические характеристики, оценка состояния в зависимости от каких-либо внешних или внутренних факторов и т.д. Соответственно, в этом случае, более предпочтительным будет использование не структуры, а класса.
Итого
Как и классы в C#, структуры позволяют определить пользовательский тип данных в вашем проекте. При этом, на первый взгляд, структуры (struct) практически ни чем не отличаются от классов, однако различия есть: во-первых, структуры относятся к типам значений, во-вторых, структуры не поддерживают механизмов наследования. Использовать или не использовать структуры — решение самого разработчика, однако, рекомендуется использовать тип struct только в том случае, если ваш пользовательский тип данных содержит минимум бизнес-логики или не содержит её вовсе.