Выбор между неизменными объектами и структурами для объектов значения

Два операнда (1 и 3) являются целыми числами, поэтому используется целочисленная арифметика (деление здесь). Объявление переменной результата как double просто приводит к возникновению неявного преобразования после деления .

Целочисленное разделение конечно возвращает истинный результат деления, округленный до нуля. Таким образом, результат 0.333... округляется до 0. (Обратите внимание, что процессор фактически не делает никакого округления, но вы можете думать об этом так же).

Также обратите внимание, что если указаны оба операнда (числа) как плавающие; 3.0 и 1.0, или даже только first , то используется арифметика с плавающей запятой, дающая вам 0.333....

22
задан Garry Shutler 22 February 2009 в 22:35
поделиться

10 ответов

, Как Вы выбираете между реализацией объекта значения (канонический пример, являющийся адресом) как неизменный объект или структура?

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

  • Класс
    • , изменяемый
    • неизменный
  • Структура
    • изменяемый
    • неизменный

, я утверждаю, что в.NET, выбор по умолчанию должен быть изменяемый класс для представления логика и неизменный класс для представления объект . Я на самом деле склонен выбирать неизменные классы даже для логических реализаций, если вообще выполнимый. Структуры должны быть зарезервированы для маленьких типов, которые эмулируют семантику значения, например, пользовательское Date тип, Complex тип числа подобные объекты. Акцент здесь находится на небольшой , так как Вы не хотите копировать большие блобы данных, и косвенность через ссылки является на самом деле дешевой (таким образом, мы не получаем много при помощи структур). Я склонен делать структуры всегда неизменными (я не могу думать о единственном исключении в данный момент). Так как это лучше всего соответствует семантике типов внутренней ценности, за которыми я нахожу хорошим правилом следовать.

14
ответ дан Konrad Rudolph 29 November 2019 в 04:06
поделиться

Существует несколько вещей рассмотреть:

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

класс А выделяется на "куче". Это - ссылочный тип, так раздавание объекта через методы не является столь же дорогостоящим.

Обычно я использую структуры для неизменных объектов, которые не являются очень большими. Я только использую их, когда существует ограниченный объем данных, сохраненный в них, или я хочу неизменность. Пример DateTime структура. Мне нравится думать, что, если мой объект не так легок как что-то как DateTime, это, вероятно, не стоит использоваться в качестве структуры. Кроме того, если мой объект не имеет смысла, раздаваемого как тип значения (также как DateTime), то не может быть полезно использовать в качестве структуры. Неизменность является ключевой здесь все же. Кроме того, я хочу подчеркнуть, что структуры не неизменны по умолчанию. Необходимо сделать их неизменными дизайном.

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

15
ответ дан Dan Herbert 29 November 2019 в 04:06
поделиться

Мне нравится использовать мысленный эксперимент:

этот объект имеет смысл, когда только пустого конструктора называют?

Редактирование в запрос Richard E

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

, Например, вероятность имеет допустимый диапазон 0-1. Используя десятичное число для представления это везде подвержено ошибке и требует проверки в каждой точке использования.

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

Вот использование в качестве примера struct для представления вероятности:

public struct Probability : IEquatable<Probability>, IComparable<Probability>
{
    public static bool operator ==(Probability x, Probability y)
    {
        return x.Equals(y);
    }

    public static bool operator !=(Probability x, Probability y)
    {
        return !(x == y);
    }

    public static bool operator >(Probability x, Probability y)
    {
        return x.CompareTo(y) > 0;
    }

    public static bool operator <(Probability x, Probability y)
    {
        return x.CompareTo(y) < 0;
    }

    public static Probability operator +(Probability x, Probability y)
    {
        return new Probability(x._value + y._value);
    }

    public static Probability operator -(Probability x, Probability y)
    {
        return new Probability(x._value - y._value);
    }

    private decimal _value;

    public Probability(decimal value) : this()
    {
        if(value < 0 || value > 1)
        {
            throw new ArgumentOutOfRangeException("value");
        }

        _value = value;
    }

    public override bool Equals(object obj)
    {
        return obj is Probability && Equals((Probability) obj);
    }

    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }

    public override string ToString()
    {
        return (_value * 100).ToString() + "%";
    }

    public bool Equals(Probability other)
    {
        return other._value.Equals(_value);
    }

    public int CompareTo(Probability other)
    {
        return _value.CompareTo(other._value);
    }

    public decimal ToDouble()
    {
        return _value;
    }

    public decimal WeightOutcome(double outcome)
    {
        return _value * outcome;
    }
}
14
ответ дан Community 29 November 2019 в 04:06
поделиться

Факторы: конструкция, требования к памяти, упаковывая.

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

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

, Что преимущество потеряно, когда экземпляры упаковываются (например, получил для анонимной функции или сохранил в неуниверсальном контейнере) - Вы даже начинаете платить дополнительный за упаковку.

<час>

, Что является "маленьким", что такое "многие"?

издержки для объекта составляют 8 байтов (IIRC) в системе на 32 бита. Обратите внимание, что с несколькими сотнями из экземпляров, это может уже решить, работает ли внутренний цикл полностью в кэше или вызывает GC's. Если Вы ожидаете десятки тысяч экземпляров, это может быть различием между выполненным по сравнению с проверкой.

От этого POV, использование структур НЕ является преждевременной оптимизацией.

<час>

Так, как эмпирические правила :

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

6
ответ дан peterchen 29 November 2019 в 04:06
поделиться

В современном мире (я думаю C# 3.5) я не вижу потребность в структурах (РЕДАКТИРОВАНИЕ: Кроме в некоторых нишевых сценариях).

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

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

Лично, я не могу вспомнить в прошлый раз, когда я использовал структуру в C#.

Редактирование

я предполагаю, что использование структуры в C# по причинам производительности является очевидным случаем Преждевременной Оптимизации <глоток> *

<глоток> *, если приложение не было представленной производительностью, и использование класса было идентифицировано как узкое место производительности

Редактирование 2

MSDN состояния:

тип структуры подходит для представления легких объектов, таких как Точка, Прямоугольник и Цвет. Хотя возможно представить точку как класс, структура более эффективна в некоторых сценариях. Например, если Вы объявите массив 1 000 Точечных объектов, то Вы выделите дополнительную память для ссылки на каждый объект. В этом случае структура является менее дорогой.

, Если Вам не нужна семантика ссылочного типа, класс, который меньше, чем 16 байтов могут быть более эффективно обработаны системой как структура.

2
ответ дан Richard Everett 29 November 2019 в 04:06
поделиться

В целом я не рекомендовал бы структуры для бизнес-объектов. В то время как Вы МОГЛИ БЫ получить небольшое количество производительности путем заголовка этого направления, поскольку Вы работаете на стеке, Вы заканчиваете тем, что ограничили себя до некоторой степени, и конструктор по умолчанию может быть проблемой в некоторых случаях.

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

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

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

Вы упоминаете адрес как свой пример. Давайте исследуем один как класс.

public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
}

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

2
ответ дан Gregory A Beamer 29 November 2019 в 04:06
поделиться

Что является стоимостью копирования экземпляров, если передано значением.

, Если высокий, затем неизменная ссылка (класс) тип, иначе (структура) значения тип.

0
ответ дан Richard 29 November 2019 в 04:06
поделиться

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

Другое беспокойство является конструктором по умолчанию. Структура всегда имеет значение по умолчанию (без параметров и общедоступный) конструктор, иначе операторы как

T[] array = new T[10]; // array with 10 values

не работали бы.

Дополнительно это является учтивым для структур, чтобы перезаписать == и эти != операторы и реализовать эти IEquatable<T> интерфейс.

0
ответ дан Michael Damatov 29 November 2019 в 04:06
поделиться

С точки зрения объектного моделирования я ценю структуры, потому что они позволяют мне использовать компилятор для объявления определенных параметров и полей как не допускающих NULL-значения. Конечно, без специальной семантики конструктора (как в Spec#), это только применимо к типам, которые имеют естественное 'нулевое' значение. (Следовательно Bryan Watt, 'хотя эксперимент' ответ.)

0
ответ дан Av Pinzur 29 November 2019 в 04:06
поделиться

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

Да, структуры могут дать отличную производительность при использовании ref, но вы должны видеть, какую память они используют. Кто контролирует память и т. Д.

Если вы не используете ref и out со структурами, они того не стоят, если вы ожидаете неприятных ошибок :-)

-2
ответ дан 29 November 2019 в 04:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: