这= =比较失败的根本原因是什么? (令我惊讶的结果)

时间:2011-04-25 18:48:51

标签: c# expression typing

背景信息:我正准备(可能)将我的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 个答案:

答案 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来获取具有相同内容的字符串的实习参考。对于相同的内容,这些实例必须是相同的实例。有些情况下,了解这个微小的细节可能是一个很大的帮助或大开眼界。