Объект == равенство не выполняется, но .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 в обоих случаях, потому что литеральные строки с одинаковым значением получают интернирование по умолчанию и, следовательно, относятся к одному и тому же объекту (например, ссылки также равны)