#c# #expression #typing
#c# #выражение #ввод
Вопрос:
Контекст: Я создаю прототип в prep для (возможно) преобразования моего приложения 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?)
Ответ №1:
Сначала приведите Tag
к string
. В реализации по умолчанию на object
, ==
сравнивает ссылки. Поскольку Tag
свойство имеет тип object
, оно использует наименьший общий ==
оператор между object
и string
, который является object
реализацией. При приведении к Tag
string
используется реализация на string
, которая является сравнением значений.
Комментарии:
1. Небольшая деталь: сравнение строк оптимизировано для того, чтобы сначала выполнять сравнение ссылок, а затем сравнивать значения.
2. Добавлена незначительная деталь: это связано с интернированием строки.
Ответ №2:
Используйте Object.Equals(treeViewItemTag, "ViewForAMs")
вместо
Ответ №3:
Если вы посмотрите на тип treeViewItemTag, вы увидите, что тип — object, а не string. Итак, когда вы используете == , вы сравниваете ссылки на два объекта. В этом случае это всегда будет возвращать false. Если вы используете Equals () вместо этого или приводите к строке, то это должно сработать.
Ответ №4:
Тег в свойстве TreeViewItem является объектом, а не строкой. == сравнивает ссылки на объекты. Чтобы сравнить строку, вы должны выполнить сравнение с помощью toString():
if (treeViewItemTag.ToString() == "ViewForAMs")
Но вы должны быть уверены, что содержит строку, иначе сравнение также завершится неудачей.
Ответ №5:
Используйте 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 (потому что оно сравнивает ссылки, а не строки).
Комментарии:
1. Это больше похоже на подход Java. При сравнении двух строк оператор == перегружен для проверки равенства значений.
2. славик, обычно ты был бы прав, но в этом случае ты ошибаешься. переменная имеет тип object {string}, а не тип string. Итак, перегрузка в этом случае не работает.
3. @slavik262, я вынужден не согласиться. Это нормально, когда оба значения имеют строковый тип. Но если одно из них является строкой, а другое — объектом, вы закончите сравнение ссылок, если вы сравниваете с использованием == . (И предупреждение от компилятора, которое легко пропустить). Этого не произойдет, если вы вызываете String . Equals(). Также вы не можете указать параметры сравнения с помощью оператора == .
4. В этом случае вы должны преобразовать объект в строку, избегая двусмысленности. В любом случае, это просто мое мнение.
Ответ №6:
‘TreeViewItem.Тег’ — это ссылка на объект. По умолчанию в C # оператор == проверяет равенство ссылок, то есть, что два объекта являются одним и тем же в памяти. В строке перегружен оператор ‘==’ для проверки равенства значений, то есть, содержат ли строки одинаковое содержимое. Однако, чтобы использовать его, вам нужно привести ‘TreeViewItem.Добавляйте тег’ к строке.
Ответ №7:
Я не свободно владею WPF, но в контексте Winforms я бы сказал, что тег имеет тип Object .
Оператор равенства для объекта сравнивает ссылки.
Если вы (или какой-либо другой читатель), возможно, захотите узнать, почему это все еще работает в некоторых случаях:
Когда вы строите строки с помощью StringBuilder или неуправляемых функций, вы не получаете так называемую промежуточную строку. Это означает, что во время выполнения у вас есть два разных объекта string, которые имеют одинаковое содержимое.
Обычно строки ссылаются на один и тот же экземпляр, за исключением случаев, когда они создаются во время выполнения, как описано выше. Вы можете вызвать String .Intern для получения ссылки intern на строку с тем же содержимым. Это обязательно должен быть один и тот же экземпляр для одного и того же содержимого. Бывают ситуации, когда знание этой крошечной детали может оказать большую помощь или открыть глаза.