Объект == равенство не выполняется, но .Equals преуспевает. Имеет ли это смысл?
Возможный дубликат:
Разница между == operator и Equals() в С#?
Две формы равенства, первая неудачная, вторая преуспевает.
(object)"abc" == (object)"abc"
false
((object)"abc").Equals((object)"abc")
true
В приведенной ниже ссылке мы видим, что "Операторы равенства в С# не являются полиморфными"
ref: Оператор равенства строк == в С#
btw: все еще не уверен, почему это проблема. Я думал, что это может быть что-то вроде этого, но это происходит не потому, что этот тест преуспевает.
static void Main(string[] args) {
var o = new classOfT<string>() { val = "abc" };
Console.WriteLine((object)o.val == "abc");
}
public class classOfT<T> {
public string val { get; set; }
}
Кстати: Я НЕ СОГЛАШАЮССЯ С ТОЧНЫМ ПРАВИЛОМ ПОСРЕДСТВОМ НА ЭТОМ ВОПРОС, НО ЭЙ.
В ответе говорится:
... Класс String содержит как статический bool Equals (строка a, string b) и статический метод bool Equals (объект a, объект b). Разница в том, что первая определяется в классе String сам, в то время как последний наследуется от класса Object (который базовый класс String)
Семантически это имеет смысл, но имеет ли он смысл в более широком контексте OO и языка С#?
Почему я беспокоюсь о вопросе? Ну, просто нашел ошибку, и я хотел бы записать это в своем мозгу под рифмой или причиной, а не под "просто помнить об этом", она укусила вас перед категорией.
Update:
в настоящее время думает об этом с точки зрения работы с примитивами (с функциональной точки зрения) против полиморфизма. Поскольку я делал все больше и больше функциональных вещей, возможно, поэтому родной язык меня смутил. Я еще не думал об этом (нет, я не прагматичен, меня привлекает дизайн языка). Спасибо, что ответили на все!
Ответы
Ответ 1
(object)"abc"
создаст ссылку на объект из строкового объекта. Таким образом,
(object)"abc" == (object)"abc"
создаст две ссылки на объекты, которые не равны.
Однако использование метода equals проверяет, равно ли значение сохраненной строки. Опять же, это не стандартная реализация всех объектов, а объекта String. Для любого настраиваемого объекта вы должны определить свою собственную реализацию метода equals для достижения такого поведения.
Ответ 2
Образец кода возвращает true.
(object)"abc" == (object)"abc"
Я думаю, что вы представили другой пример, чем код, возвращающий false в вашем приложении. CLR использует интерполяцию строк для оптимизации строк. Приведение в System.Object приведет к тому, что оператор == сравнивает ссылки и из-за функции интернирования строк, оператор == приведет к истинному. Сравнение будет возвращать только false, если параметры с обеих сторон оператора == будут ссылаться на разные строковые объекты в куче.
Проверьте, была ли сборка отмечена атрибутом [assembly: CompilationRelaxations(System.Runtime.CompilerServices.CompilationRelaxations.NoStringInterning)]
или нет.
Ответ 3
Сравнение строк должно выполняться с помощью String.Compare
,
http://blogs.msdn.com/b/abhinaba/archive/2005/10/28/486173.aspx
http://msdn.microsoft.com/en-US/vstudio/aa496123?pull=/library/en-us/dndotnet/html/StringsinNET20.asp
Я не думаю, что вы "нашли ошибку", так как Microsoft делала то же самое много раз в .NET BCL, и она становится общей, к которой мы, как разработчики, должны адаптироваться. Простой пример:
var ip1 = IPAddress.Parse("127.0.0.1");
var ip2 = IPAddress.Parse("127.0.0.1");
Вы найдете ip1 != ip2
, но ip1.Equals(ip2) == true
. Рекомендуемый способ сравнения - IPAddress.Compare(ip1, ip2)
. В любом случае, вы должны иногда что-то помнить.
Ответ 4
== operator:
Для предопределенных типов значений оператор равенства (==) возвращает true, если значения его операндов равны, в противном случае - false. Для справки типы, отличные от string, == возвращает true, если его два операнда ссылаются на тот же объект. Для типа строки == сравнивает значения строки.
Равно:
Завершается класс string, который будет "возвращать true, если obj является Строка и ее значение совпадают с этим экземпляром; в противном случае - false.
Если ваш код похож на ниже,
var s1= GetString1(); //some string object
var s2= GetString2(); //some string object containing same content as s1
(object)s1 == (object)s2
returns false - because == compares the references of the objects (which will be different if not interned)
((object)s1).Equals((object)s2)
returns true - because Equals will be called between actual strings at run time
Но в текущей форме ваш код
(object)"abc" == (object)"abc"
((object)"abc").Equals((object)"abc")
должен возвращать значение true в обоих случаях, потому что литеральные строки с одинаковым значением получают интернирование по умолчанию и, следовательно, относятся к одному и тому же объекту (например, ссылки также равны)