Подтвердить что ты не робот

Структуры - примеры реальной жизни?

Здесь существует множество вопросов о SO, касающихся различий между Structs и Classes в С#, и когда использовать тот или иной. (Ответ на один предложение: используйте структуры, если вам нужна семантика значений.) Существует множество рекомендаций о том, как выбрать тот или иной, большинство из которых сводится к: использованию класса, если вы не отвечаете этим конкретным требованиям, а затем используйте struct.

Это все имеет смысл для меня.

Однако я не могу найти реальных примеров людей, использующих структуры в системе. Я (semi-) новичок в С#, и у меня возникают проблемы с представлением конкретной ситуации, когда структуры действительно являются правильным выбором (по крайней мере, я еще не сталкивался с одним).

Итак, я обращаюсь к SO-мозгу. Каковы случаи, когда вы фактически использовали структуру в системе, в которой класс не работал бы?

4b9b3361

Ответ 1

Хорошо, класс будет работать для него, но пример, который я мог бы подумать, - это что-то вроде Point. Предполагая, что это значение x и y, вы можете использовать struct.

struct Point {
    int x;
    int y;
}

На мой взгляд, я предпочел бы иметь более простое представление пары целых чисел, чем определять использование класса с экземплярами, когда фактический объект действительно не имеет большого (или любого) поведения.

Ответ 2

Я использовал структуру для представления геолокации

struct LatLng
{
    public decimal Lattitude
    {
        get;
        set;
    }
    public decimal Longitude
    {
        get;
        set;
    }
}

это представляет собой единый объект, например, я могу добавить 2 LatLng вместе или выполнить другие операции над этим единственным объектом.

MSDN-структура

Тип структуры подходит для представляющих легкие объекты, такие как как точка, прямоугольник и цвет. Хотя можно представить точка как класс, структура больше эффективным в некоторых сценариях. Для Например, если вы объявите массив 1000 Точечных объектов, вы выделите дополнительная память для ссылки на каждый объект. В этом случае структура дешевле.

Также, если вы посмотрите на примитивные типы Int32, decimal, double и т.д., вы заметите, что все они structs, что позволяет им быть типами значений, позволяя им для реализации определенных важных интерфейсов.

Ответ 3

Структуры также обычно используются в системах графики/рендеринга. Существует много преимуществ для создания структур точек/векторов.

Рико Мариани опубликовал отличную викторину по программированию на основе ценности. Он обсудил множество причин, чтобы предпочесть структуры в конкретных ситуациях и подробно объяснил это в своем отчете о результатах теста.

Ответ 4

Денежная структура, вероятно, является одной из самых распространенных, однако номер телефона или Адрес также являются общими.

public struct Money
{
    public string Currency { get; set; }
    public double Amount { get; set; }
}

public struct PhoneNumber
{
    public int Extension { get; set; }
    public int RegionCode { get; set; }
    //... etc.
}

public struct FullName
{
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
}

Имейте в виду, что в .NET ваши структуры не должны быть больше объема памяти, чем 16 байтов, потому что, если они становятся больше, CLR должна выделять дополнительную память.

Кроме того, что structs "live" в стеке (а не куча как ссылочные типы), вы можете рассмотреть возможность использования структур, если вам нужно создать экземпляр множества одинаковых типов объектов.

Ответ 5

Ключевым примером является структура nullable types, например int?. Они используют структуры, чтобы они сохраняли семантику значений int, но предоставляли способ сделать их нулевыми без бокса и превратить их в ссылочные типы.

Вы использовали бы структуру, когда вы не хотите передавать что-либо по ссылке. Предположим, у вас есть набор данных или объект, который вы хотите передать по значению (т.е. Все, что вы передаете ему, работает со своей уникальной копией, а не ссылкой на исходную версию), тогда структура является правильным типом для использовать.

Ответ 6

Они предоставляют реализацию по умолчанию для Object.GetHashCode(), поэтому вы можете использовать структуру вместо класса, когда объект представляет собой простой набор типов без ссылки, которые вы хотите использовать в качестве ключей к словарю.

Они также полезны для сценариев сети PInvoke/interop или low-level, где вам нужен точный контроль над двоичной компоновкой структуры данных. (перейдите на сайт www.pinvoke.net для большого количества кода взаимодействия, для которого требуются структуры)

Но на самом деле, я никогда не использую их сам. Не потейте, не используя их.

Ответ 7

В основном я стараюсь НЕ использовать их. Я нахожу, что они путают других разработчиков в команде и, следовательно, не стоят усилий. Я только нашел один случай, чтобы использовать его, пользовательский тип типа, подобный Enum, мы используем генератор кода для создания из XML.

Ответ 8

Ключ для меня - определить, хочу ли я сохранить ссылку на один и тот же объект.

Что делает смысл, когда struct является частью другого объекта, но сама сущность.

В приведенном выше примере с LatLong, который, например, имеет идеальный смысл. Вам нужно скопировать значения из одного объекта в другой, а не продолжать ссылаться на один и тот же объект.

Ответ 9

Я часто использую structs для представления типа значения модели домена, который может быть представлен как перечисление, но требует произвольного неограниченного количества дискретных значений или я хочу, чтобы у него было дополнительное поведение (методы), которое вы не можете добавить в перечисление... Например, в недавнем проекте многие элементы данных были связаны с конкретным календарем Месяцем, а не с датой. Поэтому я создал структуру CalendarMonth с методами:

  • static CalendarMonth Parse (DateTime inValue);
  • static CalendarMonth Parse (строка inValue);

и метод TryParse(),

  • static bool TryParse (строка inValue, out CalendarMonth outVal);

И Свойства

  • int Месяц {get; задавать; }
  • int Year {get; задавать; }
  • DateTime StartMonthLocal {get; задавать; }
  • DateTime StartMonthUTC {get; задавать; }
  • DateTime EndMonthLocal {get; задавать; }
  • DateTime EndMonthUTC {get; задавать; }

и др.

Ответ 10

im обычно не касается "плотности данных" в моих бизнес-приложениях. Обычно я всегда использую класс, если я специально не хочу семантику значений

Это означает, что я предчувствую ситуацию, когда я хочу сравнить две из этих вещей, и я хочу, чтобы они отображались одинаково, если они имеют одинаковое значение. С классами это на самом деле больше работы, потому что мне нужно переопределить ==,! =, Equals и GetHashcode, что даже если resharper делает это для меня, это лишний ненужный код.

Поэтому, на мой взгляд, всегда используйте классы, если вы не знаете, что хотите, чтобы эти вещи сравнивались по значению (в этом случае значение компонента)

Ответ 11

Итак, я так понимаю, вы никогда не использовали DateTime (struct).

Ответ 12

Не могу поверить, что никто не упомянул XNA: в XNA почти все есть struct. Поэтому, когда вы делаете

Matrix rotation = Matrix.CreateRotationZ(Math.PiOver2);

Вы действительно создаете тип значения.

Это связано с тем, что в отличие от программирования приложений задержка в несколько миллисекунд, пока сборщик мусора не приемлем (мы получаем только 16,6 мс, чтобы отобразить весь кадр!), поэтому нам нужно как можно больше избегать распределения поэтому GC не нужно запускать так много.

Это особенно актуально для XBox 360, где GC нигде не близка к качеству на ПК - даже в среднем по одному распределению на кадр можно убить производительность!

Ответ 13

Я работал в финансовых учреждениях, где были достигнуты требования к кешированию и латентности большого масштаба с использованием структур. В принципе, структуры могут избавить сборщика мусора от работы.

См. следующие примеры:

http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/ http://00sharp.wordpress.com/2013/07/04/a-case-for-the-structpart-2/

Ответ 14

В принципе, я использую Structs для моделирования геометрических и математических данных или когда мне нужна структура данных на основе значений.

Ответ 15

Единственный раз, когда я когда-либо использовал структуру, был, когда я строил структуру Fraction:

public struct Fraction
{
   public int Numerator {get;set;}
   public int Denominator {get; set;}
   //it then had a bunch of Fraction methods like Reduce, Add, Subtract etc...
}

Я чувствовал, что он представляет значение, как и встроенные типы значений, и поэтому кодирование против него будет более естественным, если оно будет вести себя как тип значения.

Ответ 17

В некоторых критически важных ситуациях структура (тип значения и, следовательно, выделенная из стека) может быть лучше класса (ссылочного типа и, следовательно, выделена из кучи). Joe Duffy blog post " Блокировка записи/записи с одним словом" показывает реальное применение этого.

Ответ 18

В прошлом я создал StorageCapacity. Он представлял 0 байтов для N exabytes (мог бы повыситься до yottabyte, но exa показалось достаточно в то время). Структура имела смысл, так как я работал в компании по управлению хранилищем. Вы могли бы подумать, что это было довольно просто: структура с StorageUnit (перечисление) и количество (я использовал десятичную). Но когда вы добавляете в конверсии, операторы и классы для поддержки форматирования, разбора и т.д., Он складывается.

Абстракция была полезной, чтобы вы могли использовать любой StorageCapacity и представлять ее в виде байтов, килобайт и т.д. без необходимости умножать или делить на 1024 много раз.

Ответ 19

Я объяснил причины использования структур уже в другом месте (Когда использовать struct в С#), и я использовал структуры по этим причинам в реальных проектах:

Я бы выбрал использование структур по соображениям производительности, если мне нужно было хранить большое количество одного и того же типа элемента в массиве, что может произойти при обработке изображений.

Нужно использовать структуры для передачи структурированных данных между С# и С++.

Если у меня нет оснований для их использования, я стараюсь избегать их.

Я знаю, что некоторым людям нравится использовать их для реализации семантики значений, но я нахожу, что это поведение настолько отличается от "нормального" поведения классов присваивания (на С#), что вы обнаруживаете, что вам сложно отслеживать ошибки, потому что один не помнил, что объект, который был назначен или имел это поведение, потому что он был реализован как структура вместо класса. (Это случалось со мной не раз, поэтому я даю это предупреждение, так как я на самом деле был сожжен навязчивым использованием структур С#.)

Ответ 20

Я не уверен, как много это используется, но сегодня я обнаружил, что, хотя вы не можете иметь иналиаторы полей экземпляра в структурах, вы можете в классах.

Следовательно, следующий код даст ошибки компиляции, но если вы измените "struct" на "class", он скомпилируется.

    public struct ServiceType
    {
        public bool backEnd { get; set; }
        public bool frontEnd { get; set; }

        public string[] backEndServices = { "Service1", "Service2" };
        public string[] frontEndServices = { "Service3", "Service4" };
    }

Ответ 21

Структура в С# в своем сердце не больше и не меньше, чем куча переменных, склеенных вместе с клейкой лентой. Если требуется, чтобы каждая переменная определенного типа представляла связку независимых, но связанных переменных (таких как координаты точки), прикрепленных вместе с клейкой лентой, часто лучше использовать структуру открытого поля, чем класс, независимо от того, "связка" означает два или двадцать. Обратите внимание, что хотя рекомендации по структурированному классу Microsoft подходят для типов данных, которые инкапсулируют одно значение, его следует считать неприменимым для типов, целью которых является инкапсуляция независимых, но связанных значений. Чем больше степень независимости переменных, тем больше преимущества использования структуры открытого поля.

Если вы хотите использовать класс для инкапсуляции группы независимых переменных, есть два способа сделать это, ни один из которых не является ужасно удобным. Можно использовать неизменяемый класс, и в этом случае любое ненулевое место хранения этого типа класса инкапсулирует значения, хранящиеся в экземпляре, идентифицированном им, и одно место хранения может быть скопировано в другое, чтобы новый инкапсулировал те же самые значения. К сожалению, изменение одного из значений, инкапсулированных местоположением хранилища, обычно требует создания нового экземпляра, который точно так же, как старый, за исключением того, что это значение изменилось. Например, если у вас есть переменная pt типа Immutable3dPoint, и один хотел увеличить pt.X на единицу, нужно было бы сделать что-то вроде: pt = new Immutable3dPoint(pt.X+1, pt.Y, pt.Z); Возможно, допустимо, если тип только инкапсулирует три значения, но довольно раздражает, если их очень много.

Другой подход на основе классов - использовать изменяемый класс; это обычно требует, чтобы каждый обеспечивал, чтобы каждое место хранения типа класса содержало единственную ссылку в любом месте юниверса для экземпляра этого класса. Когда создается место хранения, необходимо создать новый экземпляр и сохранить там ссылку. Если вы хотите скопировать значения из места хранения P в место хранения Q, другому, нужно скопировать все поля или свойства из одного экземпляра в другой (возможно, используя метод типа CopyFrom и скажем Q.CopyFrom(P);. Обратите внимание, что если один из них говорит Q=P;, что может показаться сработавшим, но будущие попытки изменить P также изменят Q и наоборот. Переменные классы могут работать, и они могут время от времени эффективный, но очень легко повредить вещи.

Структуры с открытыми полями объединяют удобную семантику значений неизменяемых классов с удобными кусочно-модификациями, допускаемыми изменяемыми классами. Большие структуры копируются медленнее, чем ссылки на неизменяемые объекты, но стоимость модификации части структуры открытого поля зависит только от степени модификации, а не от общего размера структуры. Напротив, стоимость изменения одной части данных, инкапсулированной в неизменяемый тип класса, будет пропорциональна суммарному размеру класса.