Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

C#. Непоследовательное сопоставление

Anna | 17.06.2014 | нет комментариев
От переводчика:
Это свободный перевод блогозаписи Эрика Липперта (Eric Lippert), в прошлом одного из разработчиков языка C#. Запись оформлена в виде «вопрос-результат», я пропущу вопрос и перейду к результату, вы можете ознакомиться с вопросом в оригинале, но там ничего особенно увлекательного.

Но, для начала, я попрошу взглянуть на дальнейший код, и без гугла и компилирования, испробовать узнать что произойдет в 9 случаях сопоставления и свериться с результатами (для опроса):

int myInt = 1;
short myShort = 1;
object objInt1 = myInt;
object objInt2 = myInt;
object objShort = myShort;
Console.WriteLine(myInt == myShort);          // scenario 1
Console.WriteLine(myShort == myInt);          // scenario 2
Console.WriteLine(myInt.Equals(myShort));     // scenario 3
Console.WriteLine(myShort.Equals(myInt));     // scenario 4
Console.WriteLine(objInt1 == objInt1);        // scenario 5
Console.WriteLine(objInt1 == objShort);       // scenario 6
Console.WriteLine(objInt1 == objInt2);        // scenario 7
Console.WriteLine(Equals(objInt1, objInt2));  // scenario 8
Console.WriteLine(Equals(objInt1, objShort)); // scenario 9


Язык C# был спроектирован так, Дабы трудиться так, как этого ждет разработчик: то есть, язык гдеявственные техники и положительные техники одно и тоже. И по большей части это так. К сожалению, сопоставление это одна из частей языка, в которой есть западни.

Напишем дальнейший код, Дабы проиллюстрировать разные степени сопоставления.

Результаты

int myInt = 1;
short myShort = 1;
object objInt1 = myInt;
object objInt2 = myInt;
object objShort = myShort;
Console.WriteLine(myInt == myShort);          // scenario 1 true
Console.WriteLine(myShort == myInt);          // scenario 2 true
Console.WriteLine(myInt.Equals(myShort));     // scenario 3 true
Console.WriteLine(myShort.Equals(myInt));     // scenario 4 false!
Console.WriteLine(objInt1 == objInt1);        // scenario 5 true
Console.WriteLine(objInt1 == objShort);       // scenario 6 false!!
Console.WriteLine(objInt1 == objInt2);        // scenario 7 false!!!
Console.WriteLine(Equals(objInt1, objInt2));  // scenario 8 true
Console.WriteLine(Equals(objInt1, objShort)); // scenario 9 false!?!

Что за черт? Разберем все по-порядку.

В первом и втором случае, мы обязаны сначала определить что значит оператор ==. В C# существует больше десятка встроенных операторов == для сопоставления разных типов.

object == object
string == string
int == int
uint == uint
long == long
ulong == ulong
...

Так как не существует операторов int == short либо short == int, должен быть выбран самый подходящий оператор. В нашем случае это оператор int == int. Таким образом, short конвертируется в int и после этого две переменные сравниваются по значению. Следственно, они равны.

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

Equals(object, object) // статический способ унаследованный от object
Equals(object)         // воображаемый способ унаследованный от object
Equals(int)            // реализация способа интерфейса IEquatable<int>.Equals(int)

1-й нам не подходит потому что у нас неудовлетворительно доводов для его вызова. Из 2-х других способов, огромнее подходит способ тот, что принимает int как параметр, неизменно отменнее сконвертировать довод типа short в int, чем в object. Следственно, будет вызван Equals(int), тот, что сопоставляет две переменные типа int применяя сопоставление по значению, таким образом это выражение правдиво.

В четвертом случае мы вновь обязаны определить какой именно способ Equals будет вызван. Дерзкий экземпляр имеет тип short, тот, что вновь же имеет три способа Equals.

Equals(object, object) // статический способ унаследованный от object
Equals(object)         // воображаемый способ унаследованный от object
Equals(short)          // реализация способа интерфейса IEquatable<short>.Equals(short)

1-й и 3-й способы нам не подходят, потому что для первого у нас слишком немного доводов, а 3-й способ не будет выбран потому что нет неявного приведения типа int к short. Остается способ short.Equals(object), реализация которого равна дальнейшему коду:

bool Equals(object z)
{
  return z is short && (short)z == this;
}

То есть, Дабы данный способ вернул trueупакованный элемент должен являться типом short, и позже распаковки он должен равняться экземпляру тот, что вызвал Equals. Но, так как, передаваемый довод является типом int, способ вернет false.

В пятомшестом и седьмом, будет выбрана форма сопоставления object == object, что равнозначно вызову способа Object.ReferenceEquals. Видимо, что две ссылки равны в пятом случае и неравны в шестом иседьмом. Значения которые содержатся в переменных типа object неважны, потому что сопоставление по значению не применяется вовсе, сравниваются только ссылки.

В восьмом и девятом случае, будет использован статический способ Object.Equals, тот, что реализован дальнейшим образом:

public static bool Equals(object x, object y)
{
    if (ReferenceEquals(x, y)) return true;
    if (ReferenceEquals(x, null)) return false;
    if (ReferenceEquals(y, null)) return false;
    return x.Equals(y);
}

В восьмом случае, мы имеем две ссылки которые не равны и не равны null, следственно, будет вызванint.Equals(object), тот, что как вы можете предположить смотря на код способа short.Equals(object), реализован дальнейшим образом:

bool Equals(object z)
{
  return z is int && (int)z == this;
}

Так как довод является упакованной переменной типа int, будет произведено сопоставление по значению и способ вернет true. В девятом случае упакованная переменная имеет тип short, следственно проверка типа (z is int) завершится неудачей, и способ вернет false.

Результат:
Я показал девять разных методов сопоставления 2-х переменных, невзирая на то, что во всех случаях, сопоставляемые переменные равны единице, только в половине случаев сопоставление возвращает true. Если вы думаете, что это безрассудство и все запутанно, вы правы! Сопоставление в C# дюже лукаво.

Сколько итогов сопоставлений для вас оказались непредвиденными?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Проголосовало 99 человек. Воздержалось 22 человека.

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB