Почему является новый Тип "кортеж" в.Net 4.0 ссылочным типом (класс) и не тип значения (структура)

Кто-либо знает ответ и/или имеет мнение об этом?

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

87
задан Jack 30 October 2019 в 06:32
поделиться

3 ответа

Причина, скорее всего, в том, что только меньшие кортежи будут иметь смысл в качестве типов значений, поскольку они будут иметь небольшой объем памяти. Более крупные кортежи (то есть те, которые имеют больше свойств) фактически пострадают от производительности, поскольку они будут больше 16 байт.

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

Ах, подозрения подтвердились! См. Построение кортежа :

Первое важное решение заключалось в том, следует ли рассматривать кортежи как ссылочный или как тип значения. Поскольку они неизменяемы каждый раз, когда вы хотите изменить значения кортежа, вам нужно создать новый. Если это ссылочные типы, это означает, что может образоваться много мусора, если вы изменяете элементы в кортеже в жестком цикле .Кортежи F # были ссылочными типами, но команда чувствовала, что они могли бы добиться повышения производительности, если бы два, а возможно, три элемента кортежа вместо этого были типов значений. Некоторые команды, создававшие внутренние кортежи, использовали значения вместо ссылочных типов , потому что их сценарии были очень чувствительны к созданию множества управляемых {{1} } объекты. Они обнаружили, что использование типа значения дает им лучшую производительность. В нашем первом черновике спецификации кортежа мы сохранили двух-, трех- и четырехэлементные кортежи как типы значений, а остальные являются ссылочными типами. Однако во время совещания по проектированию, на котором присутствовали представители других языков , было решено, что этот "разделенный" дизайн будет сбивать с толку из-за {{ 1}} немного отличается семантика между двумя типами. Было установлено, что согласованность поведения и дизайна имеет более высокий приоритет, чем потенциальное повышение производительности. На основе этого ввода мы изменили дизайн так, чтобы все кортежи были ссылочными типами, хотя мы попросили команду F # провести некоторое исследование производительности, чтобы увидеть , если он испытал ускорение при использовании типа значения для некоторых размеров кортежей. У него был хороший способ проверить это, поскольку его компилятор написал в F # был хорошим примером большой программы, использующей кортежи в различных сценариях. В конце концов, команда F # обнаружила, что не улучшилась производительность , когда некоторые кортежи были типами значений вместо ссылочных типов. Это заставило нас лучше понять наше решение использовать ссылочные типы для кортежа.

43
ответ дан 24 November 2019 в 07:49
поделиться

Для двух кортежей вы всегда можете использовать KeyValuePair из более ранних версий Common Type System . Это ценностный тип.

Небольшое уточнение к статье Мэтта Эллиса будет заключаться в том, что разница в семантике использования между ссылочными типами и типами значений является лишь «незначительной», когда действует неизменяемость (что, конечно, будет иметь место здесь). Тем не менее, я думаю, что в дизайне BCL было бы лучше не вводить путаницу, связанную с переходом Tuple к ссылочному типу на некотором пороге.

4
ответ дан 24 November 2019 в 07:49
поделиться

Я не знаю, но если вы когда-нибудь использовали F#, кортежи являются частью языка. Если бы я создал .dll и возвращал тип Tuples, было бы неплохо иметь тип, в который можно было бы это поместить. Я подозреваю, что теперь, когда F# является частью языка (.Net 4), некоторые изменения в CLR были сделаны, чтобы приспособить некоторые общие структуры в F#

Из http://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records

let scalarMultiply (s : float) (a, b, c) = (a * s, b * s, c * s);;

val scalarMultiply : float -> float * float * float -> float * float * float

scalarMultiply 5.0 (6.0, 10.0, 20.0);;
val it : float * float * float = (30.0, 50.0, 100.0)
0
ответ дан 24 November 2019 в 07:49
поделиться
Другие вопросы по тегам:

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