#c# #.net #generics #boxing
#c# #.net #дженерики #боксирование
Вопрос:
Читая книгу Джона Шарпа VS 2010, там говорится, что дженерики позволяют устранить необходимость приведения, уменьшить боксирование типов значений — уменьшить? Я думал, что его удалили так же, как и кастинг? Кто-нибудь может объяснить, пожалуйста?
Ответ №1:
Это не полностью устраняет использование боксирования и приведения… это просто значительно уменьшает их. Иногда вы знаете о типах вещей больше, чем компилятор. Например, предположим, что вы подключили один и тот же обработчик событий к множеству кнопок. Совсем не лишено смысла использовать:
public void HandleClickEvent(object sender, EventArgs e)
{
// We know it will always be a button, and we want an exception if it's not
Button button = (Button) sender;
...
}
Ну вот и все — кастинг не умер.
Аналогично, боксирование все еще происходит в ситуациях, когда вы не знаете точный тип во время компиляции и не можете выразить его обобщенно. Два наиболее очевидных примера этого:
- Отражение (выборка значения свойства с помощью отражения даст вам
object
, бокс, если необходимо) -
Динамическая типизация в C # 4:
dynamic d = CreateDynamicObject(); int x = d.Foo(); // The dynamic call would have to box if necessary, // the conversion will unbox
Так что бокс тоже не умер.
Если вы только говорите о хранении значений в коллекциях, то верно, что боксирование и приведение теперь появляются в коде намного, намного реже, чем раньше. Но не все находится в коллекции, и дженерики полезны и за пределами коллекций.
Комментарии:
1. Спасибо, Джон, хотя я не настолько продвинут, чтобы понять, как первый пример (событие) относится к дженерикам :/
2. @Miria: Это не так, и в этом как раз суть: дженерики не обращаются к каждому месту, которое вы, возможно, захотите создать или упаковать / распаковать. Вот почему дженерики могут только уменьшить количество приведений / упаковок / распаковок, а не полностью устранить это.
3. О, тогда я, вероятно, спросил неправильно. Я подумал: правда ли, что при использовании дженериков (говоря только об универсальном коде) этот код не требует кастинга? И почему боксирование только сокращается?
Ответ №2:
Что помогло мне много лет назад разобраться с дженериками, так это рассмотреть возможность использования дженерика, когда:
Вы добавляете параметр к методу, который содержит информацию о типе
public object Parse(string input, Type outputType)
// replace by:
public T Parse<T>(string input)
Вы используете поле экземпляра, которое содержит информацию о типе:
class Foo
{
private Type _wrappedObjectType;
private object _wrappedObject;
}
// replace by
class Foo<T>
{
private T _wrappedObject;
}