сравнение переменной обобщенного типа с null
Сравнение переменной обобщенного типа с
null
с помощью операторов
==
и
!=
допустимо независимо от того, ограничен обобщенный тип или нет:
private static void ComparingAGenericTypeVariableWithNull(T obj) {
if (obj == null)
{ /* Этот код никогда не исполняется для значимого типа */ }
}
Так как тип
T
не ограничен, он может быть ссылочным или значимым. Во вто-
ром случае
obj
нельзя приравнять
null
. Обычно в этом случае компилятор C#
должен выдать ошибку, но этого не происходит — код успешно компилируется.
При вызове этого метода с аргументом значимого типа JIT-компилятор, обнару-
жив, что результат выполнения инструкции
if
никогда не равен
true
, просто не
сгенерирует машинный код для инструкции
if
и кода в фигурных скобках. Если
бы я использовал оператор
!=
, JIT-компилятор также не сгенерировал бы код для
инструкции
if
(поскольку условие всегда истинно), но сгенерировал бы код в фи-
гурных скобках после
if
.
Кстати, если к
Т
применить ограничение
struct
, компилятор С# выдаст ошибку,
потому что код, сравнивающий значимый тип с
null
, не имеет смысла — результат
всегда один.
сравнение двух переменных обобщенного типа
Сравнение двух переменных одинакового обобщенного типа допустимо только
в том случае, если обобщенный параметр типа имеет ссылочный тип:
331
Верификация.и.ограничения
private static void ComparingTwoGenericTypeVariables (T o1, T o2) {
if (o1 == o2) { } // Ошибка
}
В этом примере у
T
нет ограничений, и хотя можно сравнивать две переменные
ссылочного типа, сравнивать две переменные значимого типа допустимо лишь в том
случае, когда значимый тип перегружает оператор
==
. Если у
T
есть ограничение
class
, этот код скомпилируется, а оператор
==
вернет значение
true
, если пере-
менные ссылаются на один объект и полностью тождественны. Если параметр
T
ограничен ссылочным типом, перегружающим метод
operator==
, компилятор
сгенерирует вызовы этого метода в тех местах, где он встречает оператор
==
. Есте-
ственно, это относится и к оператору
!=
.
При написании кода для сравнения элементарных значимых типов (
Byte
,
Int32
,
Single
,
Decimal
и т. д.) компилятор С# сгенерирует код правильно, но для непри-
митивных значимых типов генерировать код сравнения он не умеет. Поэтому если у
параметра
Т
метода
ComparingTwoGenericTypeVariables
есть ограничение
struct
,
компилятор выдаст ошибку. А ограничивать параметр-тип значимым типом нельзя,
потому что они неявно являются запечатанными, а следовательно, не существует
типов, производных от значимого типа. Если бы это было разрешено, обобщенный
метод будет ограничен конкретным типом; компилятор C# не позволяет это делать,
поскольку эффективнее было бы использовать необобщенный метод.
Do'stlaringiz bilan baham: |