Изменение различных значений в структуре (насколько они неизменны?) - PullRequest
3 голосов
/ 09 декабря 2011

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

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

public struct SomeValues
{
    public int AnInt;
    public float AFloat;
    public string AString;
}
public SomeValues[] ArrayOfValues;
private void SomeFunctionThatRunsContinuously()
{
    /*so for every value I change, do I essentially create a whole new instance
      of SomeValues?*/

    for (int i = 0; i < ArrayOfValues.Length; i++)
    {
        //Is this another struct?
        ArrayOfValues[i].AnInt++;

        //And then another again?
        ArrayOfValues[i].AFloat += 0.33f;

        /*I realise adding letters to a string is a horrible idea 
                       -- but is it WORSE to do it in a struct?*/

        ArrayOfValues[i].AString += "s";
    }
}

Так, например, если бы у меня была структура, которая, например, содержала координаты каждого человека в 3D / 2D-пространстве (координаты были приведены в качестве примера того, когда использовать структуры), и положение людей меняется и обновляются внутри структуры типа две / три, возможно из массива, это создает новые структуры, потому что они неизменны?

Ответы [ 4 ]

0 голосов
/ 06 января 2012

Структуры не являются неизменяемыми. Хотя некоторые люди считают, что так и должно быть, большинство причин, по-видимому, делятся на три категории:

  1. Методы Struct могут изменять "this", а методы класса - нет; поскольку было бы неприятно запретить использование любых и всех методов для структур в контексте только для чтения - даже тех, которые фактически не изменяют «this» - компиляторы вместо этого обрабатывают вызовы методов для структур только для чтения, делая временные копии структур и методы работы с этими копиями; любые изменения, которые эти методы могут сделать, исчезнут, когда методы возвратятся.
  2. Некоторые люди не понимают, что структуры и классы ведут себя по-разному.
  3. Некоторые функции языка предполагают выполнение преобразований кода, которые могут работать не так хорошо с изменяемыми структурами, как с неизменяемыми структурами или классами (изменяемыми или неизменяемыми).

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

struct fancyRect {public int left,top,width,height; ....other stuff.... };

... then within some code ...
  myList = List<fancyRect>; // Assume this list has been initialized somehow
  fancyRect tempRect = myList[0];
  tempRect.left += 5;
  myList[0] = tempRect;

Влияние вышеуказанного кода на содержимое myList может быть полностью установлено только с предоставленной информацией. Было бы чище, если бы свойства могли быть представлены по ссылке, что позволило бы myList[0].left += 5, но код для структур все еще ясен и читабелен. Предположим, что tempRect были вместо класса. Какой эффект будет иметь приведенный выше код? Может ли это иметь другие последствия? Как нужно кодировать его, чтобы иметь ту же семантику, что и для структур?

0 голосов
/ 09 декабря 2011

Структура НЕ неизменна.Новый объект в памяти создается не тогда, когда вы его изменяете, а когда вы присваиваете его другой переменной или передаете в качестве аргумента какому-либо методу.

0 голосов
/ 09 декабря 2011

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

Итак для неизменяемых структур / классов :

  • не используйте открытые поля, вместо этого используйте свойства без открытого установщика.С частным сеттером все в порядке, с задним полем (из конструктора) тоже все в порядке.
  • разрешает устанавливать значения только через конструктор.
  • методы, которые могут изменить вашу структуру не изменить его, вместо этого они должны вернуть новый экземпляр (например, DateTime.AddYears).
0 голосов
/ 09 декабря 2011

Структуры не являются неизменяемыми, если вы не сделаете поля в них доступными только для чтения.

public struct SomeValues 
{ 
    public readonly int AnInt; 
    public readonly float AFloat; 
    public readonly string AString; 
} 
...