2011-04-25 12 views
7

Kontekst: Prototypuję w prep (może) konwertuję moją aplikację WinForms na WPF.jaki jest podstawowy powód, dla którego porównanie == nie powiedzie się? (zaskakujący wynik dla mnie)

robię bardzo proste obsługi widoku drzewa zdarzeń, dla których kod jest:

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(); 
} 

i XAML jest:

<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> 

Kiedy wpadłem, ja w pełni spodziewałem się zobaczyć mój siatki danych się zapełniło, ale porównanie == nie powiodło się w drugim wierszu kodu powyżej.

Debuger pokazuje to:

pytanie: dlaczego tam nie ma kompilacji lub w czasie wykonywania błędy? (To samo pytanie inaczej: co jest rzeczywiście tak, że w porównaniu wyjść operator == FAŁSZ?)

enter image description here

Odpowiedz

4

Najpierw prześlij od Tag do string. W domyślnej implementacji na object, porównuje odniesienia. Ponieważ właściwość Tag jest typu object, używa ona najniższego wspólnego operatora == między object a string, który jest implementacją object. Odlewając od Tag do string, używana jest implementacja string, która stanowi porównanie wartości.

+0

dzięki, to był poziom szczegółowości, którego szukałem. –

+0

Drobne szczegóły: Porównanie ciągów jest zoptymalizowane, aby najpierw porównać dane, a następnie dokonać porównania wartości. –

+0

Dodano drobne szczegóły: wynika to z interakcji ciągów. – Femaref

1

Zastosowanie Równa() do porównywania ciągów znaków.

AKTUALIZACJA: Lub odlewać na oba łańcuchy. Przykład z MSDN:

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

Pierwsze porównanie zwraca wartość true, ale drugi zwraca false (ponieważ porównuje referencje, a nie ciągi).

+0

Jest to bardziej podejście Java. Porównanie dwóch ciągów ma przeciążony operator == w celu przetestowania równości wartości. –

+0

slavik, zwykle masz rację, ale w tym przypadku jesteś w błędzie. var jest typu object {string}, a nie typu string. Przeciążenie nie działa w tym przypadku. – invalidsyntax

+0

@ slavik262, muszę się nie zgodzić. Jest dobrze, gdy obie wartości są typu string. Ale jeśli jeden jest ciągiem, a drugi jest obiektem, zakończy porównywanie odniesień, jeśli porównujesz używając ==. (I ostrzeżenie z kompilatora, którego łatwo przegapić). Nie stanie się tak, jeśli wywołasz String.Equals(). Ponadto nie można określić opcji porównania za pomocą operatora ==. – Dmitry

4

Zastosowanie Object.Equals(treeViewItemTag, "ViewForAMs") zamiast

+0

+1 daje mi to najczystszy kod wyniku końcowego –

2

Jeśli spojrzeć na rodzaj treeViewItemTag, widać, że typ jest przedmiotem, a nie ciąg. Więc kiedy używasz ==, porównujesz odniesienia dwóch obiektów. To zawsze zwróci fałsz w tym przypadku. Jeśli zamiast tego użyjesz funkcji Equals() lub rzutowania na ciąg znaków, to powinno działać.

1

Właściwość Tag w TreeViewItem jest obiektem, a nie łańcuchem. == porównuje odniesienia do obiektów. Aby porównać ciąg, należy zrobić porównanie przy użyciu toString():

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

Ale trzeba mieć pewność, zawiera ciąg albo porównanie będzie również niepowodzeniem.

0

'treeViewItem.Tag' jest odniesieniem do obiektu. Domyślnie w języku C# operator == sprawdza równość odniesienia, tj. Czy oba obiekty są jednym i tym samym w pamięci. Łańcuch ma przeciążonego operatora "==", aby sprawdzić równość wartości, czyli jeśli łańcuchy zawierają tę samą zawartość. Aby go użyć, musisz rzucić "treeViewItem.Tag" na ciąg znaków.

0

Nie jestem biegły w WPF, ale w kontekście WinForm powiedziałbym, że Tag jest typu Object.
Operator równości w obiekcie porównuje odniesienia.

Jeżeli możesz (lub jakiś inny czytelnik) chce wiedzieć, dlaczego to nadal działa w niektórych przypadkach:
Kiedy zbudowany ciągi poprzez pomocą StringBuilder lub funkcji niezarządzanych nie dostać so.called intern ciąg. Oznacza to, że istnieje sposób, że masz dwa różne obiekty ciągów w czasie wykonywania, które mają tę samą treść.
Zwykle ciągi znaków odnoszą się do tej samej instancji, z wyjątkiem sytuacji, gdy są budowane w środowisku wykonawczym, jak wyjaśniono powyżej. Możesz wywołać String.Intern, aby uzyskać odwołanie do ciągu strun o tej samej treści. Te są zobowiązane do tego samego wystąpienia dla tej samej treści. Są sytuacje, w których znajomość tego drobnego szczegółu może stanowić dużą pomoc lub otworzyć oczy.

Powiązane problemy