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

Являются ли структуры "быстрее", чем классы? В общем или в .NET Framework?

Так как structs являются типами значений, их данные копируются при передаче в метод в качестве аргумента. Пример:

int someInt = 7;

DoSomeMethod(someInt); // <-- This is passing the "value" 7.

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

public struct TimmysStructOfGoodness
{
    public int SomeInt1;
    public int SomeInt2;
    public int SomeInt3;
    // ... later that day ...
    public int SomeInt999;
}

а затем со ссылкой на следующий код:

TimmysStructOfGoodness someStructOfGoodness = new blah blah blah...

DoSomeMethod(someStructOfGoodness); // <-- **HERE IS WHERE THE QUESTION APPLIES!**

Является ли приведенный выше оператор попыткой выделить несколько мегабайт оперативной памяти для "копирования" моего значения типа (struct)?

Если ответ да - тогда, когда/где - линия между "быстрее" и "медленнее"?

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

ОСНОВНОЕ ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я знаю, что это не имеет никакого отношения к тому, почему вы использовали бы стихи стилей класса, и я знаю, что я никогда не буду создавать структуру с 999 полями - это всего лишь вопрос об основах и кишках и например:)

4b9b3361

Ответ 1

(обновлено, благодаря вкладам других пользователей)

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

Если (как указал Адам Робинсон) struct - это член класса, в этом случае он выделяется в кучу вместе со всем остальным.

С другой стороны, каждый раз, когда вы назначаете структуру или передаете ее функции, она копируется.

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

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

Это - если вам нужно передать его по ссылке, сделайте его классом, независимо от его размера.

Во второй мысли вы все равно можете передать struct по ссылке просто указав ref в списке параметров функции.

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

Ответ 2

Структуры и классы не просто имеют разную производительность, но и ведут себя по-разному. Вы должны использовать тот, который наиболее подходит для того типа, который вы используете. Руководящие принципы, когда использовать тот или иной, четко описаны в MSDN. Используйте конструкцию только в том случае, если применимы следующие условия:

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

Если вы передаете структуру функции, вы получите ее копию. Если ваша структура большая, то это приведет к копированию большого количества данных. Ссылка обычно реализуется как 4 байта (на x86), поэтому передача объекта требует только копирования этих 4 байтов.

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

Ответ 3

Последствия производительности для структур зависят от того, как вы используете такие структуры.

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

Структуры (типы значений в целом) могут быть выделены либо в стеке, либо в куче - в зависимости от контекста объявления. Если вы объявите его в теле метода (и не укажете его явно), структура будет в стеке. Если вы затем передаете эту структуру методу, который принимает его по значению (как в примере), он действительно будет скопирован - но в стеке. Распределение в стеке - очень эффективный процесс (BTW, куча .NET также очень эффективна), но это процесс копирования.

Вы можете, конечно, передать структуру, используя ref/out - в этом случае копирование не произойдет - ссылка на структуру будет передана методу. Это может быть или не быть желательным - поскольку это позволит вызываемому методу изменять содержимое структуры.

Структура, объявленная как член класса, будет фактически выделена в куче (как часть макета памяти класса). Если вы пройдете этот класс вокруг, структура не будет скопирована, но все равно будет доступна через ссылку на класс.

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

object x = new MyStruct( ... );  // boxed on the heap

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

Ответ 4

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

Ответ 5

Ответ на ваш вопрос: Да. Когда вы определяете структуру, каждое присваивание выполняет операцию копирования.

Не существует точной строки, которая отделяет "быструю" от "медленной", потому что существует множество факторов, которые влияют на скорость WRT на структуры, например:

< коррекция > Структуры хранятся по значению: в стеке или внутри содержащихся объектов. Таким образом, они повышают локальность кэша, так как вероятность того, что соответствующая страница уже загружена в кэш-память процессора, где произвольные страницы кучи, вероятно, не будут. </коррекции > Кроме того, структуры не позволяют переопределять метод, поэтому отправка метода также (незначительно) выполняется быстрее.

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