背景信息:我正准备(可能)将我的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?)
答案 0 :(得分:4)
首先将Tag
投射到string
。在object
的默认实现中,==
会比较引用。由于Tag
属性属于object
类型,因此它使用==
和object
之间的最低公共string
运算符,即object
实现。通过将Tag
转换为string
,可以使用string
上的实现,这是一种价值比较。
答案 1 :(得分:4)
使用Object.Equals(treeViewItemTag, "ViewForAMs")
代替
答案 2 :(得分:2)
如果查看treeViewItemTag的类型,您将看到该类型是object,而不是string。因此,当您使用==时,您正在比较两个对象的引用。在这种情况下,这总是会返回false。如果您使用Equals(),或者转换为字符串,那么它应该可以工作。
答案 3 :(得分:1)
使用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(因为它比较引用,而不是字符串)。
答案 4 :(得分:1)
TreeViewItem属性中的Tag是一个对象,而不是一个字符串。 ==正在比较对象引用。要比较字符串,您应该使用ToString():
进行比较if (treeViewItemTag.ToString() == "ViewForAMs")
但你必须确保包含一个字符串,否则比较也会失败。
答案 5 :(得分:0)
'treeViewItem.Tag'是对Object的引用。默认情况下,在C#中,==运算符检查引用相等性,即两个对象在内存中是同一个相同的。 String重载'=='运算符以检查值是否相等,即字符串是否包含相同的内容。但是要使用它,你需要将'treeViewItem.Tag'转换为字符串。
答案 6 :(得分:0)
我不熟悉WPF,但在Winforms上下文中,我会说Tag是Object类型。
Object上的相等运算符比较引用。
如果您(或其他读者)可能想知道为什么在某些情况下这仍然有效:
当您通过StringBuilder或非托管函数构建字符串时,您不会获得so.called实习字符串。这意味着,有一种方法是在运行时有两个不同的字符串对象具有相同的内容
通常,字符串引用相同的实例,除非它们是在运行时构建的,如上所述。
您可以调用String.Intern来获取具有相同内容的字符串的实习参考。对于相同的内容,这些实例必须是相同的实例。有些情况下,了解这个微小的细节可能是一个很大的帮助或大开眼界。