Есть ли какое-то преимущество в использовании общих коллекций, когда вы храните только ссылочные типы? - PullRequest
1 голос
/ 25 марта 2011

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

Я думаю, что это не совсем правильно, поскольку стек (не универсальный) может содержать только переменные ссылочного типа, а затем происходит просто приведение, а не упаковка.

EDIT: AFAIK, бокс относится к только типам значений для преобразования объектов.Это правильно или я что-то упустил?

Ответы [ 2 ]

3 голосов
/ 25 марта 2011

Если у вас есть Stack<SomeReferenceType>, то никакой (не) бокс не произойдет просто потому, что ссылки никогда не должны быть помещены в коробку.Ссылки - это «нормальный» способ работы типов в .NET - в конце концов, object - это ссылочный тип.

Редактировать: Ваш уточненный вопрос проясняет, что вы говорите о неуниверсальном варианте Stack.Вы правы, когда говорите, что в этом варианте нет необходимости блокировать и распаковывать ссылочные типы, поскольку ссылочные типы никогда не упаковываются (и действительно не могут быть упакованы).Также правильно, что если вы помещаете экземпляр подкласса object в Stack, то когда вы вынимаете элемент и пытаетесь использовать аспект экземпляра (который не является общим для всех object s)), тогда вам нужно будет привести к подклассу.

Обратите внимание, что (для ссылочных типов), хотя мы концептуально говорим о приведении к object, это не соответствует реальной операции;апкастинг (до объекта или любого другого суперкласса) бесплатный.Именно в понижении машина должна проверить, действительна ли пониженная оценка.Таким образом, простое заполнение неуниверсального варианта Stack экземплярами ссылочных типов эффективно;издержки возникают только при извлечении из приведения типов Stack и к более конкретному типу.

Почему вы предпочитаете универсальные коллекции.

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

В отличие от этого, общая коллекция даже не будет компилироваться, если выпопытка добавить значение неправильного типа.И даже если вам нужно реализовать небезопасный интерфейс, а компилятор не может отловить ошибку, вы получите все равно с тем преимуществом, что при добавлении элемента в коллекцию выдается InvalidCastException(рядом с основной причиной ошибки), а не после извлечения (вдали от основной причины ошибки).Будут ошибки в коде, и вы хотите найти их быстро и дешево, а не получать странные исключения в, казалось бы, не связанном коде.

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

1 голос
/ 25 марта 2011

Проблема в том, что класс Stack хранит объекты, которые вы в него помещаете, как object.Это означает, что каждый раз, когда вы помещаете что-либо в стек, оно будет упаковано в объект, и каждый раз, когда вы захотите использовать объект из стека, вам нужно будет снова распаковать его, чтобы получить правильный тип.

...