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

Неизменяемость структур

Возможный дубликат:
Почему изменчивые структуры злы?

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

В чем причина этого? Я вижу множество созданных Microsoft структур, которые изменяются, например, в xna. Вероятно, в BCL есть еще много.

Каковы достоинства и недостатки этого руководства?

4b9b3361

Ответ 1

Структуры должны представлять значения. Значения не меняются. Число 12 вечно.

Однако рассмотрим:

Foo foo = new Foo(); // a mutable struct
foo.Bar = 27;
Foo foo2 = foo;
foo2.Bar = 55;

Теперь foo.Bar и foo2.Bar отличается, что часто бывает неожиданным. Особенно в сценариях, подобных свойствам (к счастью, компилятор обнаружил это). Но также коллекции и т.д.; как вы когда-либо мутируете их разумно?

Потеря данных слишком проста с изменчивыми структурами.

Ответ 2

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

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

EDIT: Я только что нашел письмо, которое я написал некоторое время назад по этой теме. Это немного объясняет:

  • Это философски неверно: структура должна представлять собой какую-то фундаментальную ценность. Они в основном неизменны. Вы не можете изменить номер 5. Вы можете изменить значение переменной от 5 до 6, но вы не логически вносите изменения в это значение.

  • Это практически проблема: она создает множество странных ситуаций. Это особенно плохо, если он изменен через интерфейс. Затем вы можете начать изменять значения в коробке. Ик. Я видел много сообщений в группах новостей, которые связаны с тем, что люди пытаются использовать изменчивые структуры и сталкиваются с проблемами. Я видел очень странный пример LINQ, который был неудачным, потому что List<T>.Enumerator является структурой, например.

Ответ 3

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

Это не такая страшная вещь, но теперь мы в опасности, когда она становится "истиной Евангелия", когда на самом деле бывают случаи, когда законно является лучшим вариантом превращения структуры в изменчивость. Как и во всех случаях, есть исключения из правила.

Ответ 4

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

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

P.S. Чтобы избежать затрат на копирование изменяемых структур, они обычно сохраняются и передаются в массивы.

Ответ 5

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

public void DoSomething(MySomething something)
{
    something.Property = 10;
}

Ведется совершенно по-другому в зависимости от того, является ли MySomething struct или class. Для меня это убедительная, но не самая веская причина. Если вы посмотрите DDD объект Value, вы можете увидеть связь с тем, как следует обрабатывать структуры. Объект значения в DDD лучше всего представить как тип значения в .Net(и, следовательно, struct). Поскольку он не имеет идентификатора, он не может измениться.

Подумайте об этом с точки зрения своего адреса. Вы можете "изменить" свой адрес, но сам адрес не изменился. Фактически, у вас есть новый адрес, назначенный вам. Концептуально это работает, потому что, если вы действительно изменили свой адрес, ваши соседи по комнате тоже должны были бы двигаться.

Ответ 6

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

Минусы:. Концы хорошо освещены в существующих ответах, и большинство описанных проблем связано с одной и той же причиной - неожиданное поведение из-за семантики значений structs.. p >

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

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

Ответ 7

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

Семантика упрощается при использовании неизменяемых структур, и вы избегаете таких ловушек:

// a struct
struct Interval {
   int From { get; set; }
   int To { get; set; }
}

// create a list of structs
List<Interval> intervals = new List<Interval>();

// add a struct to the list
intervals.Add(new Interval());

// try to set the values of the struct
intervals[0].From = 10;
intervals[0].To = 20;

В результате структура в списке вообще не изменяется. Выражение Interval [0] копирует значение структуры из списка, затем вы изменяете свойство временного значения, но значение никогда не возвращается в список.

Изменить: изменил пример использования списка вместо массива.

Ответ 8

Когда вы копируете структуры вокруг, вы копируете их содержимое, поэтому, если вы измените скопированную версию, "оригинал" не будет обновлен.

Это источник ошибок, так как даже если вы знаете, что попадаете в ловушку копирования структуры (просто передавая ее методу) и изменяя копию.

Только что случилось со мной на прошлой неделе, я провел час, пытаясь найти ошибку.

Сохранение неизменяемых структур предотвращает это...

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

Ответ 9

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

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

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