Почему 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
620   4  

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# ' s dynamic функция, хотя (потому что это зависит от хорошо документированного 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

    Ничего не найдено.