Почему C# не может сравнить два типа объектов друг с другом, а VB-нет?
у меня есть два объекта в C# и не знаю, является ли он логическим или любым другим типом.
Однако, когда я пытаюсь сравнить эти C# не дает правильного ответа.
Я пробовал тот же код с VB.NET и это сработало !
может кто-нибудь сказать мне, как исправить это, если есть решение ?
C#:
object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!
VB.NET:
Dim a As Object = True
Dim b As Object = True
Dim c As Object = False
If (a = b) Then c = True
MessageBox.Show(c.ToString()) '// Outputs True
4 ответов:
в C#
==оператор (при применении к выражениям ссылочного типа) выполняет ссылка проверка равенства, если это не перегружен. Вы сравниваете две ссылки, которые являются результатом конверсии бокса, поэтому это разные ссылки.EDIT: с типами, которые перегружают
==, вы можете получить другое поведение - но это основано на времени компиляции тип выражения. Например,stringобеспечивает==(string, string):string x = new string("foo".ToCharArray()); string y = new string("foo".ToCharArray()); Console.WriteLine(x == y); // True Console.WriteLine((object) x == (object) y); // Falseздесь первое сравнение использует перегруженный оператор, но второе использует сравнение ссылок "по умолчанию".
в VB, the
=оператор делает намного больше работы - это даже не просто эквивалентно использованиюobject.Equals(x, y), как вещи, какOption Compareможет повлиять на то, как текст сравнивается.принципиально операторы не работают одинаково и не являются предназначены работать таким же образом.
в дополнение к ответу Джона, который объясняет сторону C# вещей, вот что делает VB:
в VB с
Option Strict Onсравнение через=всегда тесты на равенство значений и никогда на равенство ссылок. Фактически, ваш код даже не компилируется после переключенияOption Strict On, потому чтоSystem.Objectне определитьOperator=. Вы должны всегда есть эта опция, он ловит ошибки более эффективно, чем Венера мухоловка (хотя в вашем конкретном случае если это слабое поведение на самом деле делает правильную вещь).1на самом деле, с
Option Strict On, VB ведет себя еще строже, чем C#: в C#,a == bили вызывает вызовSomeType.operator==(a, b)или, если это не существует, вызывает сравнение равенства ссылок (что эквивалентно вызовуobject.ReferenceEquals(a, b)).в VB с другой стороны, сравнение
a = bвсегда вызывает оператор равенства.2 если вы хотите использовать сравнение равенства ссылок, вы должны использоватьa Is b(что, опять же, то же самое, чтоObject.ReferenceEquals(a, b)).
1) вот хороший признак, почему использование
Option Strict Offэто плохая идея: я использовал VB.NET почти десять лет, с момента официального релиза .NET до нескольких лет назад, и понятия не имею чтоa = bСOption Strict Off. Он делает какое-то сравнение равенства, но что именно происходит и почему, понятия не имею. Это сложнее чем C# ' sdynamicфункция, хотя (потому что это зависит от хорошо документированного API). вот что говорит MSDN:, потому что
Option Strict Onпредоставляет строгой типизации, предотвращает непреднамеренные преобразования типов с потерей данных, запрещает позднюю привязку и повышает производительность, его использование настоятельно рекомендуется.2) Джон упомянул одно исключение, строки, где сравнение равенства делает еще несколько вещей для причины обратной совместимости.
экземпляры объектов не сравниваются с оператором"==". Вы должны использовать метод "равно". С помощью оператора "= = " сравниваются ссылки, а не объекты.
попробуйте это:
public class MyObject { public MyObject(String v) { Value = v; } public String Value { get; set; } } MyObject a = new MyObject("a"); MyObject b = new MyObject("a"); if(a==b){ Debug.WriteLine("a reference is equal to b reference"); }else{ Debug.WriteLine("a reference is not equal to b reference"); } if (a.Equals(b)) { Debug.WriteLine("a object is equal to b object"); } else { Debug.WriteLine("a object is not equal to b object"); }результаты:
a reference is not equal to b reference a object is not equal to b objectа теперь попробуйте это:
public class MyObject { public MyObject(String v) { Value = v; } public String Value { get; set; } public bool Equals(MyObject o) { return (Value.CompareTo(o.Value)==0); } } MyObject a = new MyObject("a"); MyObject b = new MyObject("a"); if(a==b){ Debug.WriteLine("a reference is equal to b reference"); }else{ Debug.WriteLine("a reference is not equal to b reference"); } if (a.Equals(b)) { Debug.WriteLine("a object is equal to b object"); } else { Debug.WriteLine("a object is not equal to b object"); }результаты:
a reference is not equal to b reference a object is equal to b object
проблема в том, что оператор == в C# является вызовом статического метода (ну, может быть, не технически, но это может быть хотя бы как таковой) на основе тип времени компиляции из двух параметров. То, что фактические типы времени выполнения этих объектов не имеет значения.
на основе этого типа времени компиляции компилятор определит, какая реализация
operator ==использовать. Он может использовать значение по умолчаниюobjectреализация, она может использовать одну из числовых перегрузок предоставляется языком, или это может быть пользовательская реализация.это отличается от VB в том, что VB не определяет реализацию во время компиляции. Он ждет до времени выполнения и проверяет два параметра, которые ему даны, чтобы определить, какая реализация
==оператор следует использовать.ваш код содержит логические значения, но они находятся в переменных типа
object. Потому что переменная типаobject, компилятор C# используетobjectреализация==, который сравнивает ссылки, а не экземпляры объекта. Поскольку логические значения являются полями, они не имеют одинаковой ссылки, даже если их значения одинаковы.код VB не имеет значения, какой тип переменной. Он ждет до времени выполнения, а затем проверяет две переменные, видит, что они на самом деле обоих типов boolean, и поэтому использует boolean
==оператор реализация. Эта реализация сравнивает значения булевых значений, а не их ссылки (и булевые значения будут распакованы перед вызовом вызова этого оператора, поэтому сравнение ссылок больше не имеет смысла). Поскольку значения логических значений одинаковы, он возвращает true.
Comments