Comments 32
Упаковка действительно «тяжёлая» операция, так как требует выделения памяти. Распаковка — нет, это только копирование. При прямой работе со структурами тоже происходит копирование. Так что при распаковке никаких особых потерь в скорости нет.
0
MSDN с вами не согласен.
Цит. (смысловой перевод): упаковка и распаковка — дорогие операции. При упаковке типа значения должен быть создан новый объект. Такая операция может занять до 20 раз больше времени, чем присваивание. При распаковке операция приведения может занять в 4 раза больше времени, чем нужно для присваивания (а распаковка, как известно, всегда сопровождается явным приведением).
Цит. (смысловой перевод): упаковка и распаковка — дорогие операции. При упаковке типа значения должен быть создан новый объект. Такая операция может занять до 20 раз больше времени, чем присваивание. При распаковке операция приведения может занять в 4 раза больше времени, чем нужно для присваивания (а распаковка, как известно, всегда сопровождается явным приведением).
+5
Мне тоже кажется, что ребята из Microsoft завышают расценки — в 20 раз, в 4 раза. Однако часть проблемы в том, что операции упаковки-распаковки в некотором смысле «парные» — если есть упаковка, значит где-то понадобится и распаковка (не факт, конечно). Второе — это неявное создание копии объекта, что тоже нужно держать в уме. Всё это сочетание всё же достаточно существенно снижает производительность, чтобы сделать выбор, например, в сторону обобщений вместо object или dynamic.
Не думаю, что вселенная взорвётся от того, что где-то в коде произойдёт десяток упаковок-распаковок. Но на коллекциях объектов, при массовых «перепаковках» всё же стоит задуматься о производительности.
Не думаю, что вселенная взорвётся от того, что где-то в коде произойдёт десяток упаковок-распаковок. Но на коллекциях объектов, при массовых «перепаковках» всё же стоит задуматься о производительности.
0
Плюнь на MSDN. Вот код теста.
pastebin.com/zMReV0Bj
У меня он выводит:
Boxing: 00:00:13.9155034
Unboxing: 00:00:00.9500705
Copying: 00:00:00.7068114
pastebin.com/zMReV0Bj
У меня он выводит:
Boxing: 00:00:13.9155034
Unboxing: 00:00:00.9500705
Copying: 00:00:00.7068114
+3
если вы действительно хотите поговорить про «тонкие моменты», то не говорите, что value – stack; reference – heap. посмотрите сначала на то, что пишет Эрик Липперт blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
да и остальное на тонкости не сильно тянет.
да и остальное на тонкости не сильно тянет.
+2
Хм. Ну раз тут «тонкости», то можно и позанудствовать.
>> Ссылочные типы (...) хранятся в управляемой куче
Не типы, а инстансы объектов этих типов. Сами типы хранятся тоже в аналоге кучи, но CLR вас в той куче видеть не хотела бы.
>> кроме случая, когда тип значения является полем класса
Неправда. Вы забыли про массивы
>> [Про рефлексию]… соблюдая принцип инкапсуляции.
Не забудьте соблюсти permissions, ибо под FullTrust != всегда
Ни о чем, если честно. Какова объединяющая мысль статьи?
>> Ссылочные типы (...) хранятся в управляемой куче
Не типы, а инстансы объектов этих типов. Сами типы хранятся тоже в аналоге кучи, но CLR вас в той куче видеть не хотела бы.
>> кроме случая, когда тип значения является полем класса
Неправда. Вы забыли про массивы
>> [Про рефлексию]… соблюдая принцип инкапсуляции.
Не забудьте соблюсти permissions, ибо под FullTrust != всегда
Ни о чем, если честно. Какова объединяющая мысль статьи?
+2
1) Да, конечно, имеются ввиду экземпляры объектов ссылочного типа. Другое дело, что опускаю эти «подробности» не один я.
2) Тут можно немного пофилософствовать на тему того, что массивы в платформе .NET Framework реализуются как экземпляры класса System.Array, но если рассматривать массив как структуру данных, то вы правы. Массив — ссылочный тип, следовательно, память для него распределяется в куче.
3) А можно поподробнее?
Объединяющая мысль статьи — в C# есть особенности/возможности, о которых вы можете не знать/догадываться. Да прибудет с вами знание этой статьи!
2) Тут можно немного пофилософствовать на тему того, что массивы в платформе .NET Framework реализуются как экземпляры класса System.Array, но если рассматривать массив как структуру данных, то вы правы. Массив — ссылочный тип, следовательно, память для него распределяется в куче.
3) А можно поподробнее?
Объединяющая мысль статьи — в C# есть особенности/возможности, о которых вы можете не знать/догадываться. Да прибудет с вами знание этой статьи!
+1
>> А можно поподробнее?
blogs.msdn.com/b/shawnfa/archive/2005/03/08/389768.aspx годится?
>> да пребудет с вам
нет, спасибо :)
blogs.msdn.com/b/shawnfa/archive/2005/03/08/389768.aspx годится?
>> да пребудет с вам
нет, спасибо :)
0
кроме того в сильверлайте не все можно сделать из того, что можно в обычном дотнете
0
Автор, почитай Рихтера.
То, что ты описал не является чем-то из ряда вон выходящим.
То, что ты описал не является чем-то из ряда вон выходящим.
+6
У меня не было цели написать что-то из ряда вон выходящего. Всё мною описанное прямым или косвенным образом следует из спецификации языка, потому что по-другому и быть не может. Ничего не имею против, если кто-то всё это знает, а многие знают и больше. Но многие все учатся, и, надеюсь, я помог прояснить им некоторые моменты, дать небольшие рекомендации, конспективно отображая суть проблемы и её решение.
+4
Я ценю ваш труд, но этот топик из того разряда, что те кому надо уже знают об этом.
Ну раз уж опубликовано, то будем надеятся, что это поможет кому-то.
Если есть желаение написать что-то особенное, то было бы хорошо увидеть тему про взаимодействие managed/unmanaed (как с той, так и с другой стороны) со всеми тонкостями указателей (IntPtr, void* etc.), маршаллинга(Marshal), UnmanagedMemoryStream, StructLayout и прочие.
Ну это так, ИМХО.
Ну раз уж опубликовано, то будем надеятся, что это поможет кому-то.
Если есть желаение написать что-то особенное, то было бы хорошо увидеть тему про взаимодействие managed/unmanaed (как с той, так и с другой стороны) со всеми тонкостями указателей (IntPtr, void* etc.), маршаллинга(Marshal), UnmanagedMemoryStream, StructLayout и прочие.
Ну это так, ИМХО.
+4
В примере про GetEnumerator, типизация не совсем duck.
t в цикле main имеет тип Object.
По моему лучше типизировать:
using System.Collections.Generic;
t в цикле main имеет тип Object.
По моему лучше типизировать:
using System.Collections.Generic;
0
public IEnumerator GetEnumerator()
0
*случайно отправилось.
class Sample
{
public IEnumerator GetEnumerator()
…
}
А за СОМ сахар спасибо, не знал.
class Sample
{
public IEnumerator GetEnumerator()
…
}
А за СОМ сахар спасибо, не знал.
0
В любом случае это не duck.
foreach скрывает как раз вызов метода GetEnumerator() и тип объекта не приводится к IEnumerable
foreach скрывает как раз вызов метода GetEnumerator() и тип объекта не приводится к IEnumerable
0
угу, foreach — это никак не duck typing. duck typing в C# — это объекты dynamic.
0
Оператор foreach требует, чтобы объект итераций реазизовывал метод с определённой сигнатурой (контракт), но не требует от этого объекта реализации к.-л. интерфейса (такого, как IEnumerable). Если прочитать определение с вики, то именно такое поведение и считается утиной типизацией.
Процитирую:
>> Утиная типизация — вид динамической типизации, применяемой в некоторых языках программирования, когда границы использования объекта определяются его текущим набором методов и свойств, в противоположность наследованию от определённого класса. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу.
В нашем случае можно сказать, что оператор foreach считает объект коллекцией, если тот реализует метод GetEnumerator().
Процитирую:
>> Утиная типизация — вид динамической типизации, применяемой в некоторых языках программирования, когда границы использования объекта определяются его текущим набором методов и свойств, в противоположность наследованию от определённого класса. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу.
В нашем случае можно сказать, что оператор foreach считает объект коллекцией, если тот реализует метод GetEnumerator().
+2
>>>При помощи механизма отражения можно изменить значение даже private-поля класса.
Понятно, что применять это строить только в случае крайней необходимости, соблюдая принцип инкапсуляции.
Более того можно менять readonly поля.
Понятно, что применять это строить только в случае крайней необходимости, соблюдая принцип инкапсуляции.
Более того можно менять readonly поля.
+1
после предложения «C# — простой язык, благодаря простоте живёт и PHP.» завис.
этот тонкий момент точно не все знают:
типы значений хранятся в стеке приложения (кроме случая, когда тип значения является полем класса).
этот тонкий момент точно не все знают:
типы значений хранятся в стеке приложения (кроме случая, когда тип значения является полем класса).
+2
Если быть точным, то типы значений храняться в стеке потока.
0
Если быть точным, то типы значений обычно храняться в стеке потока.
0
Если быть ещё точнее, то типы значений обычно хранятся в стеке логического управляемого потока .NET, который не обязательно однозначно отображается на физический поток операционной системы.
В итоге имеем: объекты типов значений хранятся в стеке управляемого потока среды .NET, за исключением случаев, когда объект типа значения является полем класса или элементом массива. С другой стороны, объекты ссылочного типа всегда размещаются в управляемой куче процесса.
p.s. Язык C++/CLI позволяет создать массив значений в стеке.
В итоге имеем: объекты типов значений хранятся в стеке управляемого потока среды .NET, за исключением случаев, когда объект типа значения является полем класса или элементом массива. С другой стороны, объекты ссылочного типа всегда размещаются в управляемой куче процесса.
p.s. Язык C++/CLI позволяет создать массив значений в стеке.
0
Вот вот! Фраза «благодаря простоте живет и PHP» просто убила…
0
Sign up to leave a comment.
Тонкие моменты C#