Comments 61
Вывод: Это не структуры плохие, это их неправильно применяют. Название топика замануха?
Структуры — это абсолютно нормально, особенно если надо связать C/C++ c C#. Просто надо понимать разницу между типами значений и типами ссылками.
Мне лично кажется, что структуры — пережиток неуправляемого прошлого (как вы и заметили).
они полезны и вне контекста неуправляемого кода. Ну к примеру ваш метод должен вернуть тикет в котором 2 ключа типа GUID. У вас только 2 варианта.
1) протащить через аргументы(out/ref или объект куда сложить), но это право кривое решение
2) вернуть структуру, тем самым отложив пробуждение GC(а это страшно, господа)
1) протащить через аргументы(out/ref или объект куда сложить), но это право кривое решение
2) вернуть структуру, тем самым отложив пробуждение GC(а это страшно, господа)
Можно вернуть класс. Можно и структуру, конечно, именно тут и работает ремарка про здравый смысл.
А что если возвращать Tuple[Guid,Guid]?
Кортеж это ссылочный тип. Почему они сделали его таким, учитывая что структуры более оптимальное решение?
Вот тут это обсудили:
stackoverflow.com/questions/2410710/why-is-the-new-tuple-type-in-net-4-0-a-reference-type-class-and-not-a-value-ty
Вот тут это обсудили:
stackoverflow.com/questions/2410710/why-is-the-new-tuple-type-in-net-4-0-a-reference-type-class-and-not-a-value-ty
Не будьте столь категоричными! Смотрите мой пост ниже!
Или вот еще одно применение из реального мира.
В Managed DirectX, XNA объекты типа Matrix, Vector, Point являются структурами. Полагаю будь они by-ref, то пришлось бы очень много раз их копировать и абандомить.
Так происходит с Matrix в System.Drawing
Это примитивные типы, они не должны храниться в куче. Только в стеке или объекте.
В Managed DirectX, XNA объекты типа Matrix, Vector, Point являются структурами. Полагаю будь они by-ref, то пришлось бы очень много раз их копировать и абандомить.
Так происходит с Matrix в System.Drawing
Это примитивные типы, они не должны храниться в куче. Только в стеке или объекте.
И ещё такой пример
for (int i = 0; i
for (int i = 0; i
Здесь, я думаю, структуры нужны именно для unmanaged перехода в directX (хотя, конечно, могу и ошибаться)
они by design должны передаваться по значению, иначе их поведение становится неэффективным с точки зрения памяти и сборки мусора. Все кроме Matrix не покидают пределов среды исполнения, и не используются для связи с unmanaged кодом.
Кто сейчас вспомнит про заполнение Vertex буфера векторами и флотами, то это не передача в unmanaged, а сериализация.
Кто сейчас вспомнит про заполнение Vertex буфера векторами и флотами, то это не передача в unmanaged, а сериализация.
Есть неуправляемое настоящее и неуправляемое будущее, так как работать например вплотную с шиной или процессором из управляемого кода просто не возможно.
P.S.: Возможности есть, но они сильно вырываются из контекста языка, как правило, или очень громоздкие.
P.S.: Возможности есть, но они сильно вырываются из контекста языка, как правило, или очень громоздкие.
Господин Sane, настоятельно рекомендую ознакомится с книгой CLR via C# Джефрри Рихтера, дабы понять для чего существуют структуры в .Net и в каких местах они дают преимущество!
Честно говоря, не увидел у Рихтера ничего, чему бы я противоречил в посте.
Да, не противоречит. Ладно, пойдём от противного: когда лучше всего использовать структуры?
Это можно прочитать у Рихтера: The type acts as a primitive type, Instances of the type are small (approximately 16 bytes or less), Instances of the type are large (greater than 16 bytes) and are not passed as method parameters or returned from methods. К последнему я бы добавил все-таки пару слов про массивы.
В догонку:
Unless you need reference type semantics, a class that is smaller than 16 bytes may be more efficiently handled by the system as a struct.
msdn.microsoft.com/en-us/library/ah19swz4%28VS.71%29.aspx
Unless you need reference type semantics, a class that is smaller than 16 bytes may be more efficiently handled by the system as a struct.
msdn.microsoft.com/en-us/library/ah19swz4%28VS.71%29.aspx
и не только! Господин Olostan ниже уже написал ответ, который я имел в виду. Это подробно описано у Рихтера, Вы книгу невнимательно читали!
используйте IEnumerable или в крайнем случае IList (но только как ReadOnlyCollection)Такие типы данных неизменяемые?
int, long и всё остальное — зло. Так и запишем.
они by-value, но не структуры. Они примитивы
В C# это синонимы, а вообще нет.
Чойрт, это топик знаний и добра.
В C# это синонимы, а вообще нет.
Чойрт, это топик знаний и добра.
Иимхо основная польза от структур — жесткий контроль над циклом жизни: создали в стеке, вышли из метода — и нет структуры. garbage collector отдыхает.
При умелом использовании структур можно получить громадную прибыль по производительности, если используется много мелких container-like сущностей.
А использовать как immutable… увольте.
При умелом использовании структур можно получить громадную прибыль по производительности, если используется много мелких container-like сущностей.
А использовать как immutable… увольте.
Жесткий контроль над временем жизни достигается с помощью using — для чего он и был придуман. Использовать структуры только для этого — забивать гвозди микроскопом.
жизненный цикл, о котором вы только что сказали, не есть время жизни.
После Dispose объект живет еще долго. Для справки using это try {… } finally { obj.Dispose() }
После Dispose объект живет еще долго. Для справки using это try {… } finally { obj.Dispose() }
В управляемом мире, четсно говоря, время жизни объекта уже не важно. В принципе, оно так же не важно в неуправляемом, но там концепция «время жизни» хорошо совпало с «предопределнным поведением» в виде неявного вызова деструктора. В дотнет эти два понятия разделили и добавили возможность все-таки их совместить с помощью финалайзеров.
как уже заметили — using — это скорее «мягкий» контроль. Сборщик мусорка как захочет, так и освободит.
А вот с помощью структур ты точно знаешь, что контейнер (прошу заметить, я не называю это классом или объектом — именно сущность, которая содержит в себе некоторую информацию) будет освобожденна именно в тот момент, когда метод завершит свою работу.
Именно по этому и есть boxing — когда тебе надо продлить время жизни сущности за пределы вызова метода происходит boxing и сущность попадает в хип, и дальше идет уже игра с отслеживанием ссылок на объект в хипе. Когда не надо — сущность живет в стеке, и пропадает после выхода.
Сразу отвечу на следующий коммент про «время жизни не важно» — согласен. Но хорошее понимание времени жизни данных дает возможность более тонкой настройки производительности.
И ее нужно делать только после того, как профайлинг показал что именно это является «узким горлышком» — например наличие в периоды упада производительности большого количества мелких объектов. Но не в коем случае на уровне дизайна, так как структуры действительно добавляют довольно серьезные (тем, что мало-заметные) подводные камни, описанные в топике.
А вот с помощью структур ты точно знаешь, что контейнер (прошу заметить, я не называю это классом или объектом — именно сущность, которая содержит в себе некоторую информацию) будет освобожденна именно в тот момент, когда метод завершит свою работу.
Именно по этому и есть boxing — когда тебе надо продлить время жизни сущности за пределы вызова метода происходит boxing и сущность попадает в хип, и дальше идет уже игра с отслеживанием ссылок на объект в хипе. Когда не надо — сущность живет в стеке, и пропадает после выхода.
Сразу отвечу на следующий коммент про «время жизни не важно» — согласен. Но хорошее понимание времени жизни данных дает возможность более тонкой настройки производительности.
И ее нужно делать только после того, как профайлинг показал что именно это является «узким горлышком» — например наличие в периоды упада производительности большого количества мелких объектов. Но не в коем случае на уровне дизайна, так как структуры действительно добавляют довольно серьезные (тем, что мало-заметные) подводные камни, описанные в топике.
К вопросу об immutability: вон Андерс Хельсберг в своих интервью постоянно намекает на то что в C# недостаточно конструктов для описания immutability. Значит ли это что мы увидим
public readonly class MyClass
или похожие декларации? На самом деле с этим море проблем – даже тот же F# позволяет менять элементы массива при том что все, в принципе, immutable.F# позволяет менять элементы массива — потому что массив по определению мутабельная структура данных.
Да, именно этому и посвящен второй вывод.
Вот тут идет обсуждение немутабельных массивов: stackoverflow.com/questions/1432937/immutable-arrays-in-net-c-reasonable-approach
У Эрика Липперта есть хорошая серия статей про Immutability in C# (2007-2008)
blogs.msdn.com/b/ericlippert/archive/tags/immutability/
blogs.msdn.com/b/ericlippert/archive/tags/immutability/
Я всегда был уверен, что структуры хранятся в стеке, то есть куча и сборщик мусора тут ни при чем. Так что абзац там про Large Object Heap меня как-то удивил.
Наверное, если бы структуры в принципе были бы плохими, их бы в .NET не включили. Так что плохи не структуры, а изменяемые структуры, потому, что просто написать код, который делает не то, что хочет разработчик. Эрик Липперт упоминает об этом при первой удобной возможности.
Выводы статьи совершенно некорректны.
1. Все классы структур нужно делать неизменяемыми (immutable).
2. Структуры нужно использовать тогда, когда это удобно.
3. Структуры, передаваемые в методы по ссылке (ключевые слова ref и out) передаются, кто бы мог подумать — по ссылке, а не по значению — копирования не происходит, производительность не страдает.
4. Необходимо соблюдать инкапсуляцию. Если метод класса возвращает некоторый объект, модификация которого затронет состояние экземпляра класса, то класс должен позаботится о предотвращении такой модификации. Например, если требуется вернуть внутренний массив, нужно вернуть Array.AsReadOnly(source) а не сам source.
Это же всё прописные истины ООП, которые верны для любого объектно-ориентированного языка верхнего уровня.
Выводы статьи совершенно некорректны.
1. Все классы структур нужно делать неизменяемыми (immutable).
2. Структуры нужно использовать тогда, когда это удобно.
3. Структуры, передаваемые в методы по ссылке (ключевые слова ref и out) передаются, кто бы мог подумать — по ссылке, а не по значению — копирования не происходит, производительность не страдает.
4. Необходимо соблюдать инкапсуляцию. Если метод класса возвращает некоторый объект, модификация которого затронет состояние экземпляра класса, то класс должен позаботится о предотвращении такой модификации. Например, если требуется вернуть внутренний массив, нужно вернуть Array.AsReadOnly(source) а не сам source.
Это же всё прописные истины ООП, которые верны для любого объектно-ориентированного языка верхнего уровня.
нет структур — нет проблем :)
в java структур нет
в java структур нет
э… я конечно не волшебник, я только учусь, но в книжке написано что структуры стоит использовать для выигрыша в скорости, жертвуя чистотой ООП.
точнее там написано что структуры не стоит использовать без особой необходимости.
не совсем понял каким образом структура защищает данные если, опять же в книжке, написано что они почти ничем не отличаются от классов кроме отсутствия наследования (?) и места хранения ну и ссылочного типа вызова. Вызов экземпляра классе вроде бы тоже может быть оформлен в виде ссылки (?)
В общем вы меня ещё больше запутали.
точнее там написано что структуры не стоит использовать без особой необходимости.
не совсем понял каким образом структура защищает данные если, опять же в книжке, написано что они почти ничем не отличаются от классов кроме отсутствия наследования (?) и места хранения ну и ссылочного типа вызова. Вызов экземпляра классе вроде бы тоже может быть оформлен в виде ссылки (?)
В общем вы меня ещё больше запутали.
поистинну
"… любые методы получают только копию и не в силах ничего подменить"
эээ… а использование волшебного слова ref?
эээ… а использование волшебного слова ref?
Только запутали еще больше после этой статьи, так и не указав конкретно где использовать структуры.
Рекомендации от Рихтера — habrahabr.ru/blogs/net/103063/#comment_3204281.
Sign up to leave a comment.
Еще одна причина, почему структуры — это плохо