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

Что лучше для хранилища данных Struct/Classes?

Мы видели много обсуждений в SO относительно класса vs struct в С#. В основном закончились выводы, в которых говорилось о распределении памяти кучи/стек. Рекомендуем использовать структуры в небольших структурах данных.

Теперь у меня есть ситуация, чтобы решить простой хранилище данных среди этих двух вариантов. Currenlty в нашем приложении имеет тысячи классов, просто действует как простые хранилища данных (только открытые публичные поля), и они передаются между различными модулями и службами.

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

Прежде чем приступать к этому, мне нужны советы экспертов, которые испытали эту борьбу.

  • Правильно ли я понимаю?
  • Я видел, что большинство ORM имеют классы в качестве хранилищ данных. Поэтому я сомневаюсь, что есть причины идти наперекор классам вместо структур. что бы это было?
4b9b3361

Ответ 1

Я сделал бы выбор на основе следующих критериев

  • ссылочный тип и семантика типа значения. Если 2 объекта равны только, если они являются одним и тем же объектом, это указывает на тип ссылочного типа semantics = > class. Если значение его членов определяет равенство (например, 2 DateTimes равны, если оба представляют один и тот же момент времени, даже если они представляют собой два разных объекта), тип значения semantics = > struct
  • Память объекта. Если объект огромен и часто распределен, то его структура будет потреблять стек намного быстрее, поэтому я бы предпочел использовать его как класс. Напротив, я предпочел бы избежать штрафа GC за небольшие типы значений; поэтому сделайте их структурой.
  • Вы можете сделать объект неизменным? Я считаю, что структуры отлично подходят для "объектов ценности" - из книги DDD.
  • Вы столкнулись бы с каким-то бокс-распаковкой, основанным на использовании этого объекта? Если да, перейдите для класса.

Ответ 2

Структуры

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

Ответ 3

Довольно классное, не столь известное преимущество Structs over Classes заключается в том, что в структурах есть автоматическая реализация GetHashcode и Equals.
Это очень полезно, когда для словарей требуются ключи

Структурная реализация GetHashcode и Equals основана на двоичном содержимом экземпляров структуры + отражение для ссылочных элементов (например, членов String и других экземпляров классов)

Таким образом, следующий код работает для GethashCode/Equals:

public struct Person
{
    public DateTime Birthday { get; set; }
    public int Age{ get; set; }
    public String Firstname { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
        Person p2 = new Person { Age = 44, Birthday = new DateTime(1971, 5, 24), Firstname = "Emmanuel" };
        Debug.Assert(p1.Equals(p2));
        Debug.Assert(p1.GetHashCode() == p2.GetHashCode());
    }
}

Оба утверждения успешны, когда Person является структурой Оба утверждения терпят неудачу, если Person является классом вместо struct

Ссылка: https://msdn.microsoft.com/en-Us/library/2dts52z7%28v=vs.110%29.aspx

С уважением, лучшее кодирование

Ответ 4

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

Итак. Если вы не знаете, что делаете, просто придерживайтесь классов.

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

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

EDIT: для случая, который вы описываете, структуры не будут работать!

Ответ 5

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

С другой стороны, есть много веских причин для использования классов с неизменяемым состоянием (think string).

Ответ 6

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

Некоторые люди предположили, что владельцы данных, которые изменяются, не должны быть структурами. Я категорически не согласен. Сущности, которые существуют для хранения данных, во многих случаях должны быть structs особенно, если они изменяемы. Эрик Липперт неоднократно публиковал, что он считает изменчивые типы значений злыми (поиск по меткам "изменчивый" и "struct" ). Конечно, верно, что .net позволяет делать определенные вещи с помощью изменяемых структур, которые он не должен, и не позволяет удобно некоторым вещам, которые он должен, но структурам POD ( "Обычные старые данные" ), которые не имеют мутирующих методов, но вместо этого выставляют все свое состояние через общедоступные поля, имеют очень полезную согласованность в своем поведении, которое не используется ни с каким другим типом данных. Использование структуры POD может смутить кого-то, кто не знаком с тем, как они работают, но сделает программу более читаемой для всех, кто это делает.

Рассмотрим, например, следующий код, предполагая, что EmployeeInfoStruct содержит только типы значений и неизменяемые типы, такие как String:

[employeeInfoStruct is a struct containing the following field]
public Decimal YearlyBonus;

[someEmployeeContainer is an instance of a class which includes the following method]
EmployeeInfoStruct GetEmployeeInfo(String id);  // Just the signature--code is immaterial

[some other method uses the following code]
EmployeeInfoStruct anEmployee = someEmployeeContainer.GetEmployeeInfo("123-45-6789");
anEmployee.YearlyBonus += 100;

Эрик Липперт жалуется, что вышеуказанный код изменит значение в anEmployee, но это изменение не повлияет на контейнер. Я бы предположил, что хорошая вещь - любой, кто знает, как работают структуры, может смотреть на вышеприведенный код и знать, что запись в структурную переменную затронет эту переменную, но не повлияет ни на что другое, если программа позже не использует какой-либо другой метод (возможно, SetEmployeeInfo), чтобы сохранить эту переменную где-то.

Теперь замените EmployeeInfoStruct на EmployeeInfoClass, который имеет свойство read/write типа YearlyBonus. Используя только вышеприведенную информацию, что можно сказать о взаимосвязи между написанием для какого-либо рабочего сервера и anEmployee? В зависимости от реализации класса anEmployee (который, если EmployeeInfoClass не запечатан, может быть или не быть фактически EmployeeInfoClass) и someEmployeeContainer, отношения между объектами могут быть чем угодно. Записывает:

  • Не влияют на другие
  • Обновите другое в режиме 'natural'
  • Коррумпируйте другой каким-либо образом

С помощью структур, содержащих только поля типов значений или классов неизменяемых, семантика всегда будет # 1. Не нужно смотреть на код самой структуры или код контейнера, чтобы знать это. В отличие от этого, если anEmployee.Salary или someEmployeeContainer.GetEmployee является виртуальным, невозможно действительно узнать, что такое семантика.

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

Ответ 7

Думаю, у тебя есть правильная идея. Структуры создаются для имитации типов данных. Они основаны на стоимости, а не на основе ссылок. Если вы посмотрите документацию MSDN для большинства базовых классов данных (int, double, decimal, ect.), Все они основаны на структурах. Тем не менее, однако, по этой же причине структуры не следует злоупотреблять. Комната для хранения всего всего в этой структуре выделяется сразу после ее создания, когда классы просто выделяют место для ссылки на все внутри. Если данные находятся в достаточно маленьких кусках, где это не проблема, а структуры - это путь. Если это проблема, обратитесь к классам. Если вы не знаете, как лучше всего придерживаться того, с чем вы знакомы.

Ответ 8

Я помню один совет, приведенный в MSDN, который должен быть не более 16 или 21 байт. Ищет ссылку, но пока не могу ее найти.

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

Ответ 9

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

Здесь вы можете найти ориентир: http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/