2011-04-25 17 views
7

Bối cảnh: Tôi đang tạo mẫu để chuẩn bị (có thể) chuyển đổi ứng dụng WinForms sang WPF.lý do cơ bản so sánh == này là gì? (Kết quả đáng ngạc nhiên đối với tôi)

tôi làm handler xem cây sự kiện rất đơn giản mà mã là:

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

và XAML là:

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

Khi tôi chạy nó, tôi dự kiến ​​đầy đủ để xem lưới dữ liệu của tôi nhận được dân cư nhưng so sánh == không thành công trên dòng thứ hai của mã ở trên.

Trình gỡ lỗi hiển thị điều này:

CÂU HỎI: tại sao không có lỗi biên dịch hoặc thời gian chạy? (Cùng một câu hỏi một cách khác: những gì đang thực sự được so sánh như vậy mà kết quả đầu ra toán tử == FALSE?)

enter image description here

Trả lời

4

Truyền trước tiên Tag đến string. Trong triển khai mặc định trên object, == so sánh tham chiếu. Vì thuộc tính Tag thuộc loại object, thuộc loại này sử dụng toán tử phổ biến nhất == giữa objectstring, đây là triển khai object. Bằng cách truyền Tag đến string, việc triển khai trên string được sử dụng, đây là một so sánh giá trị.

+0

cảm ơn, đó là mức độ chi tiết mà tôi đã theo dõi. –

+0

Chi tiết nhỏ: So sánh chuỗi được tối ưu hóa để so sánh tham chiếu trước và sau đó thực hiện so sánh giá trị. –

+0

Đã thêm chi tiết nhỏ: Đó là do việc thực hiện chuỗi ký tự. – Femaref

1

Sử dụng Equals() để so sánh chuỗi.

CẬP NHẬT: Hoặc truyền cả hai chuỗi. Một ví dụ từ MSDN:

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

Việc so sánh đầu tiên trả về true, nhưng lợi nhuận thứ hai sai (vì nó so sánh tài liệu tham khảo, không dây).

+0

Đây là một phương pháp tiếp cận Java. Một so sánh giữa hai chuỗi có toán tử == bị quá tải để kiểm tra tính bình đẳng giá trị. –

+0

slavik, thông thường bạn sẽ đúng, nhưng trong trường hợp này bạn đã sai. var là kiểu đối tượng {string}, không phải kiểu chuỗi. Vì vậy, tình trạng quá tải không hoạt động trong trường hợp này. – invalidsyntax

+0

@ slavik262, tôi phải không đồng ý. Không sao cả khi cả hai giá trị thuộc loại chuỗi. Nhưng nếu một là một chuỗi và một là một đối tượng, bạn sẽ kết thúc so sánh tài liệu tham khảo nếu bạn đang so sánh bằng cách sử dụng ==. (Và một cảnh báo từ trình biên dịch dễ bị bỏ sót). Điều này sẽ không xảy ra nếu bạn đang gọi String.Equals(). Ngoài ra, bạn không thể chỉ định các tùy chọn so sánh với toán tử ==. – Dmitry

4

Sử dụng Object.Equals(treeViewItemTag, "ViewForAMs") thay

+0

+1 điều này mang lại cho tôi (imho) mã kết quả cuối cùng sạch sẽ khôn ngoan nhất –

2

Nếu bạn nhìn vào các loại treeViewItemTag, bạn sẽ thấy rằng các loại là đối tượng, không phải chuỗi. Vì vậy, khi bạn sử dụng ==, bạn đang so sánh các tham chiếu của hai đối tượng. Điều đó sẽ luôn trả về false trong trường hợp này. Nếu bạn sử dụng Equals() thay vào đó, hoặc cast vào một chuỗi, thì nó sẽ hoạt động.

1

Thẻ trong thuộc tính TreeViewItem là một đối tượng chứ không phải chuỗi. Các == là so sánh tham chiếu đối tượng. Để so sánh chuỗi, bạn nên làm việc so sánh sử dụng ToString():

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

Nhưng bạn phải chắc chắn chứa một chuỗi hoặc khác so sánh cũng sẽ thất bại.

0

'treeViewItem.Tag' là tham chiếu đến đối tượng. Theo mặc định trong C#, toán tử == kiểm tra tính bình đẳng tham chiếu, tức là, hai đối tượng là một và giống nhau trong bộ nhớ. Chuỗi có toán tử '==' bị quá tải để kiểm tra giá trị bình đẳng, tức là, nếu các chuỗi chứa cùng nội dung. Để sử dụng nó mặc dù, bạn cần phải cast 'treeViewItem.Tag' vào một chuỗi.

0

Tôi không thành thạo với WPF, nhưng trong ngữ cảnh Winforms, tôi có thể đã nói rằng Thẻ thuộc loại Object.
Toán tử bình đẳng trên đối tượng so sánh tham chiếu.

Nếu bạn (hoặc một số người đọc khác) có thể muốn biết tại sao điều này vẫn hoạt động trong một số trường hợp:
Khi bạn xây dựng chuỗi thông qua phương tiện của StringBuilder hoặc chức năng không được quản lý, bạn không nhận được một chuỗi tập so.called. Điều đó có nghĩa là, có một cách mà bạn có hai đối tượng chuỗi riêng biệt trong thời gian chạy có cùng nội dung.
Thông thường, các chuỗi tham chiếu đến cùng một cá thể, trừ khi chúng được xây dựng tại thời gian chạy như đã giải thích ở trên. Bạn có thể gọi String.Intern để nhận tham chiếu thực tập của một chuỗi có cùng nội dung. Những người bị ràng buộc là cùng một ví dụ cho cùng một nội dung. Có những tình huống mà biết được chi tiết nhỏ bé này có thể là một sự trợ giúp lớn hoặc mở mắt.