Когда следует использовать структуру вместо класса?

MSDN говорит, что вы должны использовать структуры, когда вам нужны легкие объекты. Существуют ли другие сценарии, когда структура предпочтительнее над классом?

Edit:
Некоторые люди забыли, что:
1. Структуры могут иметь методы!
2. Структуры не имеют возможностей наследования.

Другое Редактировать:
Я понимаю технические отличия, у меня просто нет хорошего отношения к КОГДА использовать структуру.

Ответы

Ответ 1

MSDN имеет ответ: Выбор между классами и структурами.

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

Не определяйте структуру, если тип имеет все следующие характеристики:

  • Он логически представляет одно значение, подобное примитивным типам (целое, двойное и т.д.).
  • У него размер экземпляра меньше 16 байт.
  • Это неизменный.
  • Его не нужно часто вставлять в бокс.

Ответ 2

Я удивлен, что не прочитал ни одного из предыдущих ответов, которые я считаю наиболее важным аспектом:

Я использую structs, когда мне нужен тип без идентификатора. Например, трехмерная точка:

public struct ThreeDimensionalPoint
{
    public readonly int X, Y, Z;
    public ThreeDimensionalPoint(int x, int y, int z)
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }

    public override string ToString()
    {
        return "(X=" + this.X + ", Y=" + this.Y + ", Z=" + this.Z + ")";
    }

    public override int GetHashCode()
    {
        return (this.X + 2) ^ (this.Y + 2) ^ (this.Z + 2);
    }

    public override bool Equals(object obj)
    {
        if (!(obj is ThreeDimensionalPoint))
            return false;
        ThreeDimensionalPoint other = (ThreeDimensionalPoint)obj;
        return this == other;
    }

    public static bool operator ==(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z;
    }

    public static bool operator !=(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return !(p1 == p2);
    }
}

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

Ответ 3

У Билла Вагнера есть глава об этом в его книге "Эффективный С#" (http://www.amazon.com/Effective-Specific-Ways-Improve -Ваш/др/0321245660). Он заключает, используя следующий принцип:

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

Если вы ответите "да" на все 4 вопроса: используйте struct. В противном случае используйте класс.

Ответ 4

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

Также см. предыдущие вопросы, например

В чем разница между структурой и классом в .NET?

Ответ 5

Я использовал бы structs, когда:

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

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

Ответ 6

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

Ответ 7

Если объект будет неизменен, вопрос о том, использовать ли структуру или класс, обычно будет скорее результатом, чем семантикой. В 32/64-битной системе ссылки на классы требуют хранения 4/8 байт, независимо от количества информации в классе; копирование ссылки на класс потребует копирования 4/8 байт. С другой стороны, каждый отдельный экземпляр класса будет содержать 8/16 байт служебных данных в дополнение к содержащейся в нем информации и стоимости памяти ссылок на нее. Предположим, что требуется массив из 500 объектов, каждый из которых содержит четыре 32-битных целых числа. Если объект является типом структуры, массив потребует 8000 байт независимо от того, все ли 500 объектов идентичны, все разные или где-то между ними. Если объект является типом класса, массив из 500 ссылок займет 4000 байт. Если эти ссылки указывают на разные объекты, для объектов потребуются дополнительные 24 байта (12 000 байт для всех 500), в общей сложности 16 000 байт - в два раза больше стоимости хранения типа структуры. С другой стороны, из кода создан один экземпляр объекта, а затем скопирован ссылка на все 500 слотов массива, общая стоимость будет 24 байта для этого экземпляра и 4000 для массива - всего 4 024 байта. Большая экономия. Немногие ситуации будут работать так же хорошо, как и последний, но в некоторых случаях может быть возможно скопировать некоторые ссылки на достаточное количество слотов массива, чтобы сделать такой обмен полезным.

Если сущность должна быть изменчивой, вопрос о том, следует ли использовать класс или структуру, в некоторых отношениях проще. Предположим, что "Вещь" - это либо структура, либо класс, который имеет целое поле, называемое x, и делает следующий код:

  Thing t1,t2;
  ...
  t2 = t1;
  t2.x = 5;

Требуется ли, чтобы последний оператор влиял на t1.x?

Если Thing является типом класса, t1 и t2 будут эквивалентны, то есть t1.x и t2.x также будут эквивалентны. Таким образом, второй оператор будет влиять на t1.x. Если Thing является структурным типом, t1 и t2 будут разными экземплярами, то есть t1.x и t2.x будут ссылаться на разные целые числа. Таким образом, второй оператор не будет влиять на t1.x.

Уменяемые структуры и изменяемые классы имеют принципиально разные формы поведения, хотя .net имеет некоторые особенности при обработке структурных мутаций. Если требуется поведение типа значения (это означает, что "t2 = t1" скопирует данные из t1 в t2, оставив t1 и t2 в виде отдельных экземпляров), и если вы можете жить с причудами в .net-обработке типов значений, используйте структуры. Если вы хотите семантику значения типа, но .net quirks приведет к нарушению семантики значения типа в одном приложении, используйте класс и mumble.

Ответ 8

Использовать класс if:

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

Использовать структуру, если:

  • Он будет действовать как примитивный тип (int, long, byte и т.д.).
  • Он должен иметь небольшой объем памяти.
  • Вы вызываете метод P/Invoke, который требует, чтобы структура была передана посредством значение.
  • Вам нужно уменьшить влияние сбора мусора на производительность приложения.
  • Его поля должны быть инициализированы только по умолчанию. Это значение будет равно нулю для числовых типов, false для типов Boolean и null для ссылочных типов.
    • Обратите внимание: в С# 6.0 у структур может быть конструктор по умолчанию, который можно использовать для инициализации поля структур для значений небезопасности.
  • Вам не нужно наследовать базовый класс (кроме ValueType, из которого все наследуемые структуры).
  • Вам не требуется полиморфное поведение.

Ответ 9

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

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

Ответ 10

Как сказал @Simon, структуры предоставляют семантику "значение-тип", поэтому, если вам нужно подобное поведение со встроенным типом данных, используйте struct. Поскольку structs передаются по копии, вы хотите убедиться, что они небольшие по размеру, около 16 байт.

Ответ 11

Кроме того, превосходные ответы выше:

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

Они никогда не могут быть установлены в Ничего.

Установка структуры = Nothing, устанавливает все значения своих значений по умолчанию.

Ответ 12

Хм...

Я бы не использовал сбор мусора в качестве аргумента для/против использования structs vs classes. Управляемая куча работает так же, как стек - создание объекта просто помещает его в вершину кучи, что почти так же быстро, как выделение в стеке. Кроме того, если объект недолговечен и не переживает цикл GC, освобождение освобождается, поскольку GC работает только с доступной памятью. (Поиск в MSDN, есть серия статей по управлению памятью .NET, я просто слишком ленив, чтобы их копать).

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

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

Ответ 13

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

Ответ 14

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