в чем основная причина неудачного сравнения ==? (удивительный результат для меня) - PullRequest
7 голосов
/ 25 апреля 2011

Контекст: я готовлю прототипы для подготовки к (возможно) преобразованию моего приложения WinForms в WPF.

Я делаю очень простой обработчик событий в виде дерева, код которого:

var treeViewItem = (TreeViewItem)e.NewValue;
var treeViewItemTag = treeViewItem.Tag;
if (treeViewItemTag == "ViewForAMs")
{
    ObjectQuery<AccountManagerView> oq = entities.AccountManagerViews;
    var q =
        from c in oq
        select c;
    dataGrid1.ItemsSource = q.ToList();
}

и XAML:

<Window x:Class="AccountingWpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <DockPanel>
        <TreeView Name="treeView1" ItemsSource="{Binding Folders}"
          SelectedItemChanged="treeView1_SelectedItemChanged">
            <TreeViewItem Header="Account Manager View" Tag="ViewForAMs"/>
        </TreeView>
        <DataGrid AutoGenerateColumns="True" Name="dataGrid1" />
    </DockPanel>
</Window>

Когда я запустил его, я полностью ожидал, что моя сетка данных будет заполнена, но сравнение == не удалось во второй строке кода выше.

Отладчик показывает это:

ВОПРОС: почему не было ошибок компиляции или времени выполнения? (тот же вопрос по-другому: что на самом деле сравнивается так, что оператор == выводит FALSE?)

enter image description here

Ответы [ 7 ]

4 голосов
/ 25 апреля 2011

Используйте Object.Equals(treeViewItemTag, "ViewForAMs") вместо

4 голосов
/ 25 апреля 2011

Сначала сотворите Tag до string.В реализации по умолчанию object, == сравнивает ссылки.Поскольку свойство Tag имеет тип object, оно использует самый низкий общий оператор == между object и string, который является реализацией object.При приведении Tag к string используется реализация на string, которая представляет собой сравнение значений.

2 голосов
/ 25 апреля 2011

Если вы посмотрите на тип treeViewItemTag, вы увидите, что типом является объект, а не строка.Поэтому, когда вы используете ==, вы сравниваете ссылки двух объектов.Это всегда будет возвращать false в этом случае.Если вы вместо этого используете Equals () или приводите к строке, это должно сработать.

1 голос
/ 25 апреля 2011

Тег в свойстве TreeViewItem является объектом, а не строкой. == сравнивает ссылки на объекты. Чтобы сравнить строку, вы должны сделать сравнение, используя ToString ():

if (treeViewItemTag.ToString() == "ViewForAMs")

Но вы должны быть уверены, что содержит строку, иначе сравнение также не удастся.

1 голос
/ 25 апреля 2011

Используйте Equals () для сравнения строк.

ОБНОВЛЕНИЕ: Или приведите оба к строкам. Пример из MSDN:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine((object)a == (object)b);

Первое сравнение возвращает true, а второе возвращает false (потому что сравниваются ссылки, а не строки).

0 голосов
/ 25 апреля 2011

Я не владею WPF, но в контексте Winforms я бы сказал, что Tag имеет тип Object.
Оператор равенства на объекте сравнивает ссылки.

Если вы (или какой-либо другой читатель) захотите узнать, почему это все еще работает в некоторых случаях:
Когда вы строите строки с помощью StringBuilder или неуправляемых функций, вы не получаете внутреннюю строку так называемого. Это означает, что есть способ, которым у вас есть два различных строковых объекта во время выполнения, которые имеют одинаковое содержимое.
Обычно строки ссылаются на один и тот же экземпляр, за исключением случаев, когда они создаются во время выполнения, как описано выше. Вы можете вызвать String.Intern, чтобы получить внутреннюю ссылку на строку с тем же содержимым. Это обязательно один и тот же экземпляр для одного и того же контента. Бывают ситуации, когда знание этой крошечной детали может быть большим подспорьем или откровением.

0 голосов
/ 25 апреля 2011

treeViewItem.Tag - это ссылка на объект.По умолчанию в C # оператор == проверяет равенство ссылок, т. Е. Два объекта одинаковы в памяти.В строке есть перегруженный оператор '==' для проверки на равенство значений, то есть если строки содержат одинаковое содержимое.Чтобы использовать его, вам нужно привести 'treeViewItem.Tag' к строке.

...