积极答复者
重载Equals和GetHashCode的问题

问题
-
public class Test
{
public Test() { } public int Id { get; set; }
public string TName { get; set; }
public TestSeries TSeries { get; set; }
public TestType TType { get; set; }
public bool IsComplete { get; set; }
public string Remark { get; set; }
public override bool Equals(object obj)
{
if (this == obj) return true; if (obj == null || this.GetType() != obj.GetType())
{
return false;
}
Test hb = (Test)obj;
if (this.TSeries == null)
{
if (hb.TSeries != null)
{
return false;
}
}
else
{
if (!this.TSeries.Equals(hb.TSeries))
{
return false;
}
}
if (this.TType == null)
{
if (hb.TType != null)
{
return false;
}
}
else
{
if (!this.TType.Equals(hb.TType))
{
return false;
}
}
return ((this.Id == hb.Id) && (this.TName == hb.TName)
&& (this.Remark == hb.Remark)
&& (this.IsComplete == hb.IsComplete)
);
}
public override int GetHashCode()
{
int HashCodeId = this.Id;
int HashCodeTName = this.TName == null ? 0 : this.TName.GetHashCode();
int HashCodeTSeries = this.TSeries == null ? 0 : this.TSeries.GetHashCode();
int HashCodeTType = this.TType == null ? 0 : this.TType.GetHashCode();
int HashCodeRemark = this.Remark == null ? 0 : this.Remark.GetHashCode();
int HashCodeIsComplete = this.IsComplete.GetHashCode();
return HashCodeId ^ HashCodeTName ^ HashCodeTSeries ^ HashCodeTType ^ HashCodeRemark ^ HashCodeIsComplete;
}
请问这个类重载Equals和GetHashCode的问题出在那儿?
答案
-
hi,
基本上,没事的话不需要override,除非你有特别需求
个人最常用的方式是比较两物件里的栏位是否都相同,看你提供的例子,也是想要这样做
http://www.dotblogs.com.tw/yc421206/archive/2012/12/17/85732.aspx
GetHashCode 是用来返回唯一值,会出错可能是集合里面的值有重复。
或许你也可以参考以下的写法
http://www.dotblogs.com.tw/yc421206/archive/2013/01/05/86781.aspx
http://component.codeplex.com/SourceControl/changeset/view/28740#661301秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
- 已标记为答案 ThankfulHeartModerator 2013年2月8日 8:32
全部回复
-
Hi 百里无二,
欢迎来到MSDN中文论坛。
强烈建议你看一下Guidelines for Overloading Equals() and Operator == (C# Programming Guide).其中如果要重载GetHashCode和Equals这两个方法的话,需要继承自System.Object。 就像MFC的基类要继承CWnd一样。GetHashCode和Equals已经存在于基类中,但是你这个类必须制定这个基类。
Jason Wang [MSFT]
MSDN Community Support | Feedback to us
-
-
public class Test { public Test() { } public int Id { get; set; } public string TName { get; set; } public bool IsComplete { get; set; } public string Remark { get; set; } public override bool Equals(object obj) { if (this == obj) return true; if (obj == null || this.GetType() != obj.GetType()) { return false; } Test t = (Test)obj; return ((this.Id == t.Id) && (this.TName == t.TName) && (this.Remark == t.Remark) && (this.IsComplete == t.IsComplete) ); } public override int GetHashCode() { int HashCodeId = this.Id; int HashCodeTName = this.TName == null ? 0 : this.TName.GetHashCode(); int HashCodeRemark = this.Remark == null ? 0 : this.Remark.GetHashCode(); int HashCodeIsComplete = this.IsComplete.GetHashCode(); return HashCodeId ^ HashCodeTName ^ HashCodeRemark ^ HashCodeIsComplete; } }
<Window x:Class="WpfApplication1.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"> <Grid> <Button Content="获取数据1" Height="23" HorizontalAlignment="Left" Margin="12,38,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> <Button Content="获取数据2" Height="23" HorizontalAlignment="Left" Margin="12,82,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" /> <ListBox Name="lstTestData" Height="177" HorizontalAlignment="Left" Margin="127,38,0,0" VerticalAlignment="Top" Width="120" DisplayMemberPath="TName"/> <GroupBox Header="详细信息" Height="176" HorizontalAlignment="Left" Margin="288,39,0,0" Name="groupBox1" VerticalAlignment="Top" Width="200"> <Grid Name="gridDetailed" DataContext="{Binding SelectedItem, ElementName=lstTestData,Mode=OneWay}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="67*" /> <ColumnDefinition Width="121*" /> </Grid.ColumnDefinitions> <TextBox Height="23" Text="{Binding Path=TName}" HorizontalAlignment="Left" Margin="21,19,0,0" Name="textBox1" VerticalAlignment="Top" Width="87" Grid.Column="1" /> <Label Content="TName:" Height="28" HorizontalAlignment="Left" Margin="21,15,0,0" Name="label1" VerticalAlignment="Top" Grid.ColumnSpan="2" /> <CheckBox Name="cbIsComplete" Content="是否完成" IsChecked="{Binding Path=IsComplete}" Height="16" HorizontalAlignment="Left" Margin="21,66,0,0" VerticalAlignment="Top" Grid.Column="1" /> <Button Content="更新" Height="23" HorizontalAlignment="Left" Margin="24,121,0,0" Name="button3" VerticalAlignment="Top" Width="75" Click="button3_Click" Grid.Column="1" /> </Grid> </GroupBox> </Grid> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace WpfApplication1 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { ObservableCollection<Test> data = new ObservableCollection<Test>(); for (int i = 0; i < 6; i++) { Test t = new Test() { Id = i, IsComplete = false, TName = i.ToString(), }; data.Add(t); } lstTestData.ItemsSource = data; } private void button2_Click(object sender, RoutedEventArgs e) { ObservableCollection<Test> data = new ObservableCollection<Test>(); for (int i = 0; i < 8; i++) { Test t = new Test() { Id = 10 + i, IsComplete = true, TName = (10 + i).ToString(), }; data.Add(t); } lstTestData.ItemsSource = data; } private void button3_Click(object sender, RoutedEventArgs e) { Test test = gridDetailed.DataContext as Test; if (test!=null) { test.IsComplete = cbIsComplete.IsChecked.HasValue ? cbIsComplete.IsChecked.Value : false; } } } }
1,点击获取数据。(这是listbox出现了构造的数据项)
2,listbox中选择一项。(这时对应的详细信息框中相应的信息出现)
3,修改“是否完成”,原本是没有选择,现在选择,然后点击“更新”
4,再回到list选择其他任一项
5,再次选择修改项
6,再次选择其他任何一项,这时就会出现异常在Test类中不重载GetHashCode就不会出现这个问题了,我很纠结这是为什么?
还有就是重载GetHashCode有没有什么比较好的参考?
-
-
请把项目直接打包(完整,zip),传送到SkyDrive中我们下载看看呢?
-
hi,
基本上,没事的话不需要override,除非你有特别需求
个人最常用的方式是比较两物件里的栏位是否都相同,看你提供的例子,也是想要这样做
http://www.dotblogs.com.tw/yc421206/archive/2012/12/17/85732.aspx
GetHashCode 是用来返回唯一值,会出错可能是集合里面的值有重复。
或许你也可以参考以下的写法
http://www.dotblogs.com.tw/yc421206/archive/2013/01/05/86781.aspx
http://component.codeplex.com/SourceControl/changeset/view/28740#661301秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
- 已标记为答案 ThankfulHeartModerator 2013年2月8日 8:32
-
百里无二,
现在我怀疑你的Equals代码会不会抛出异常?
因为你传入的参数是object,而且内部使用了强制转换:
Test hb = (Test)obj;
这是不安全的,建议:Test tst = obj as Test; if(tst!=null) { ………… } return false;
- 已标记为答案 Jason Dot WangModerator 2013年2月8日 8:14
- 取消答案标记 ThankfulHeartModerator 2013年2月8日 8:32