Операторы равенства делегатов

Каждый тип делегата неявно предоставляет следующие стандартные операторы сравнения:

bool operator ==(System.Delegate x, System.Delegate y);

bool operator !=(System.Delegate x, System.Delegate y);

Два делегата считаются равными, если выполняется одно из следующих условий.

· Если один из экземпляров делегата равен null, то они равны, только они оба равны null.

· Если делегаты имеют разный тип во время выполнения, то они не могут быть равны.

· Если у обоих экземпляров делегата есть список вызова (§15.1), то они равны, только если их списки вызова имеют одну длину и каждая запись в списке вызова одного делегата равна (в соответствии с определением ниже) соответствующей записи по порядку в списке вызова другого делегата.

Равенство записей списка вызова определяется следующими правилами.

· Если две записи списка вызова ссылаются на один статический метод, то записи равны.

· Если две записи списка вызова ссылаются на один нестатический метод одного целевого объекта (определяется операторами равенства ссылочных значений), то записи равны.

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

Операторы равенства и значение NULL

Операторы == и != допускают, что один операнд был значением обнуляемого типа, а второй литералом null, даже если для операции не существует стандартного или пользовательского оператора (обычного или с нулификацией).

Для операции одного из видов

x == null null == x x != null null != x

где x является выражением обнуляемого типа, если при разрешении перегрузки операторов (§7.2.4) не удается найти применимый оператор, то результат вычисляется на основании свойства HasValue для x. В частности, первые два вида операции преобразуются в!x.HasValue, а два последних вида преобразуются в x.HasValue.

Оператор is

Оператор is используется для динамической проверки, можно ли сравнивать тип объекта во время выполнения с указанным типом. Результат операции E is T, где E — это выражение, а T — тип, является логическим значением, которое указывает, можно ли провести преобразование E в тип T с помощью преобразования ссылки, преобразования упаковки или преобразования отмены упаковки. После замены всех параметров типа на аргументы типа операция вычисляется следующим образом.

· Если E является анонимной функцией, возникает ошибка времени компиляции

· Если E является группой методов или литералом null или если E имеет ссылочный или обнуляемый и значение E равно NULL, то результат равен false.

· Иначе пусть D обозначает динамический тип E следующим образом.

o Если E имеет ссылочный тип, D является типом времени выполнения для экземпляра, на который ссылается E.

o Если E имеет обнуляемый тип, D является базовым типом этого обнуляемого типа.

o Если E имеет необнуляемый тип значения, D имеет тип E.

· Результат операции зависит от D и T следующим образом.

o Если T имеет ссылочный тип, то результат равен true, если D и T имеют одинаковый тип, если D имеет ссылочный тип и существует неявное преобразование ссылки из D в T или если D имеет тип значения и существует преобразование упаковки из D в T.

o Если T имеет обнуляемый тип, результат равен true, если D является базовым типом T.

o Если T является необнуляемым типом значения, результат равен true, если D и T имеют одинаковый тип

o Иначе результат равен false.

Обратите внимание, что пользовательские преобразования в операторе is не учитываются.

Оператор as

Оператор as используется для явного преобразования значения в указанный ссылочный тип или обнуляемый тип. В отличие от выражения приведения типа (§7.7.6) оператор as никогда не вызывает исключения. Вместо этого, если указанное преобразование невозможно, возвращается значение null.

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

· Из E в T существует преобразование идентификации (§6.1.1), неявное преобразование обнуляемых типов (§6.1.4), неявное преобразование ссылочных типов (§6.1.6), преобразование упаковки (§6.1.7), явное преобразование обнуляемых типов (§6.2.3), явное преобразование ссылочных типов (§6.2.4) и преобразование отмены упаковки (§6.2.5).

· Тип E или T является открытым.

· E является литералом null.

Если тип времени компиляции E не является dynamic, операция E as T дает такой же результат, как и

E is T ? (T)(E) : (T)null

за исключением того, что E вычисляется только один раз. Компилятор может проводить оптимизацию операции E as T, чтобы при ее обработке выполнялась только одна динамическая проверка типа в отличие от двух динамических проверок типа в расширении выше.

Если тип времени компиляции E является dynamic, то, в отличие от оператора приведения, оператор as не имеет динамической привязки (§7.2.2). Таким образом, развертывание в данном случае будет следующим:

E is T ? (T)(object)(E) : (T)null

Обратите внимание, что некоторые преобразования, например пользовательские преобразования нельзя использовать с оператором as и вместо них следует использовать выражения приведения типа.

В этом примере

class X
{

public string F(object o) {
return o as string; // OK, string is a reference type
}

public T G<T>(object o) where T: Attribute {
return o as T; // Ok, T has a class constraint
}

public U H<U>(object o) {
return o as U; // Error, U is unconstrained
}
}

параметр T для G имеет ссылочный тип, поскольку у него есть ограничение класса. Напротив, параметр типа U для H не имеет ссылочного типа, поэтому использование оператора as в H запрещено.

Логические операторы

Операторы &, ^ и | называются логическими операторами.

and-expression:
equality-expression
and-expression & equality-expression

exclusive-or-expression:
and-expression
exclusive-or-expression ^ and-expression

inclusive-or-expression:
exclusive-or-expression
inclusive-or-expression | exclusive-or-expression

Если операнд логического оператора имеет тип dynamic во время компиляции, то он динамически связан (§7.2.2). В этом случае тип времени компиляции выражения — dynamic, а разрешение, приведенное ниже, будет иметь место во время выполнения при использовании типа времени выполнения тех операндов, которые имеют тип dynamic во время компиляции.

Для операции вида x op y, где op является одним из логических операторов, чтобы выбрать конкретную реализацию оператора, применяется разрешение перегрузки (§7.3.4). Операнды преобразуются в типы параметров выбранного оператора, а тип результата является типом возвращаемого значения этого оператора.

Стандартные логические операторы описываются в следующих разделах.

Наши рекомендации