C#, почему структура потребности, если класс может покрыть его?

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

Править: не видьте веские причины использовать структуру

Структура подобна классу со следующими основными отличиями:

  • Структура является типом значения, тогда как класс является ссылочным типом.
  • Структура не поддерживает наследование (кроме неявного получения из объекта).
  • Структура может иметь всех участников, класс может, кроме следующего:
  • Конструктор без параметров
  • Финализатор
  • Виртуальные участники

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

16
задан Chris Dwyer 19 February 2010 в 21:48
поделиться

9 ответов

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

Например, в Noda Time мы довольно широко используем их как эффективный способ представления таких вещей, как моменты, без накладных расходов на задействованный объект.

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

16
ответ дан 30 November 2019 в 17:15
поделиться

Обычно используйте класс.

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

3
ответ дан 30 November 2019 в 17:15
поделиться

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

Подробности см. в Викторина Рико Мариани о производительности + Ответы.

2
ответ дан 30 November 2019 в 17:15
поделиться

1, производительность. В некоторых случаях, используя структуры, мы получаем гораздо лучшую производительность.
2, неизменяемость данных. Изменив какое-либо свойство структуры, вы получите новую структуру. Это очень полезно в некоторых случаях
3, лучше контролировать представление в памяти. Мы можем точно определить, как структура расположена в памяти, и это позволяет нам быстро и эффективно сериализовать и десериализовать некоторые двоичные данные.

0
ответ дан 30 November 2019 в 17:15
поделиться

Структуры полезны просто потому, что они передаются по значению, что на самом деле может быть полезно в определенных алгоритмах. На самом деле это то, что классы НЕ МОГУТ делать.

struct ArrayPointer<T>
{
    public T[] Array;
    public int Offset;
}

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

2
ответ дан 30 November 2019 в 17:15
поделиться

Его практически необходимо использовать для взаимодействия с базовой структурой данных, используемой Win32 API. Я полагаю, что по этой причине может быть очень большая причина иметь его в .net.

0
ответ дан 30 November 2019 в 17:15
поделиться

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

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

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

0
ответ дан 30 November 2019 в 17:15
поделиться

Зачем использовать структуру , когда работает класс ? Потому что иногда класс не работает.

В дополнение к причинам производительности, упомянутым Ридом Копси (краткая версия: меньшее количество объектов, которые GC должен отслеживать, что позволяет GC лучше выполнять свою работу), есть одно место, где структуры должны быть Используется: P / Invoke для функций, которым требуются структуры по значению или элементы структуры.

Например, предположим, что вы хотите вызвать функцию CreateProcess () . Далее предположим, что вы хотите использовать структуру STARTUPINFOEX для параметра lpStartupInfo в CreateProcess () .

А что такое STARTUPINFOEX ? Это:

typedef struct _STARTUPINFOEX {
    STARTUPINFO                    StartupInfo;
    PPROC_THREAD_ATTRIBUTE_LIST    lpAttributeList;
} STARTUPINFOEX, *LPSTARTUPINFOEX;

Обратите внимание, что STARTUPINFOEX содержит STARTUPINFO в качестве своего первого члена. STARTUPINFO - это структура.

Поскольку классы являются ссылочными типами, если мы объявим соответствующий тип C # следующим образом:

[StructLayout(LayoutKind.Sequential)]
class STARTUPINFO { /* ... */ }

class STARTUPINFOEX { public STARTUPINFO StartupInfo; /* ... */ }

Соответствующий макет в памяти будет неправильным , поскольку STARTUPINFOEX.StartupInfo будет указатель (4 байта на платформах ILP32), НЕ структура (как требуется, размер 68 байтов на платформах ILP32).

Итак, для поддержки вызова произвольных функций, которые принимают произвольные структуры (в чем и заключается суть P / Invoke), необходимо одно из двух:

  1. Полная поддержка типов значений. Это позволяет C # объявить тип значения для STARTUPINFO , который будет иметь правильный макет в памяти для маршалинга (т.е. поддержка struct , как в C #).

  2. Некий альтернативный синтаксис в структурах P / Invokeable, который будет информировать маршаллер среды выполнения о том, что этот член должен быть представлен как тип значения, а не как указатель.

(2) - это работоспособное решение (и, возможно, использовалось в J / Direct в Visual J ++; я не помню), но, учитывая, что правильные типы значений более гибкие, включите ряд оптимизаций производительности, которые иначе невозможно и разумно использовать в сценариях P / Invoke, неудивительно, что C # поддерживает типы значений.

9
ответ дан 30 November 2019 в 17:15
поделиться
Другие вопросы по тегам:

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