问题:.net中的distinct方法对于自定义的类(class model )去重时失效。问题分析:
model1:
1 public class TestModel1 2 { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 public string Address { get; set; } 6 }
model2:
public class TestModel2 { protected bool Equals(TestModel2 other) { return Id == other.Id && string.Equals(Name, other.Name) && string.Equals(Address, other.Address); } public override int GetHashCode() { unchecked { int hashCode = Id; hashCode = (hashCode*397) ^ (Name != null ? Name.GetHashCode() : 0); hashCode = (hashCode*397) ^ (Address != null ? Address.GetHashCode() : 0); return hashCode; } } public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; return Equals((TestModel2) obj); } }
Model3:
public class TestModel3 { public int Id { get; set; } public string Name { get; set; } public string Address { get; set; } } public class ListTestModel3 : IEqualityComparer<TestModel3> { public bool Equals(TestModel3 x, TestModel3 y) { if (x.Id == y.Id && x.Name == y.Name && x.Address == y.Address) { return true; } return false; } public int GetHashCode(TestModel3 obj) { return 0; } }
主程序:
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 InitData(); 7 8 } 9 10 private void InitData() 11 { 12 13 var model1s = new List<TestModel1>(); 14 var model2s = new List<TestModel2>(); 15 var model3s = new List<TestModel3>(); 16 for (int i = 0; i < 3; i++) 17 { 18 var model1 = new TestModel1() 19 { 20 Id = 10001, 21 Name = "张三", 22 Address = "中国-上海" 23 }; 24 var model2 = new TestModel2() 25 { 26 Id = 10001, 27 Name = "张三", 28 Address = "中国-上海" 29 }; 30 var model3 = new TestModel3() 31 { 32 Id = 10001, 33 Name = "张三", 34 Address = "中国-上海" 35 }; 36 model1s.Add(model1); 37 model2s.Add(model2); 38 model3s.Add(model3); 39 } 40 41 for (int i = 0; i < 3; i++) 42 { 43 var model1 = new TestModel1() 44 { 45 Id = 10002, 46 Name = "张三", 47 Address = "中国-上海" 48 }; 49 var model2 = new TestModel2() 50 { 51 Id = 10002, 52 Name = "张三", 53 Address = "中国-上海" 54 }; 55 var model3 = new TestModel3() 56 { 57 Id = 10002, 58 Name = "张三", 59 Address = "中国-上海" 60 }; 61 model1s.Add(model1); 62 model2s.Add(model2); 63 model3s.Add(model3); 64 } 65 for (int i = 0; i < 3; i++) 66 { 67 var model1 = new TestModel1() 68 { 69 Id = 10001, 70 Name = "李四", 71 Address = "中国-上海" 72 }; 73 var model2 = new TestModel2() 74 { 75 Id = 10001, 76 Name = "李四", 77 Address = "中国-上海" 78 }; 79 var model3 = new TestModel3() 80 { 81 Id = 10001, 82 Name = "李四", 83 Address = "中国-上海" 84 }; 85 model1s.Add(model1); 86 model2s.Add(model2); 87 model3s.Add(model3); 88 } 89 for (int i = 0; i < 3; i++) 90 { 91 var model1 = new TestModel1() 92 { 93 Id = 10002, 94 Name = "李四", 95 Address = "中国-上海" 96 }; 97 var model2 = new TestModel2() 98 { 99 Id = 10002, 100 Name = "李四", 101 Address = "中国-上海" 102 }; 103 var model3 = new TestModel3() 104 { 105 Id = 10002, 106 Name = "李四", 107 Address = "中国-上海" 108 }; 109 model1s.Add(model1); 110 model2s.Add(model2); 111 model3s.Add(model3); 112 } 113 var model4s = (from m in model1s 114 select new TestModel1 115 { 116 Id = m.Id, 117 Name = m.Name, 118 Address = m.Address 119 }).ToList().Distinct(); 120 dataGridView1.DataSource = model1s; 121 dataGridView2.DataSource = model2s; 122 dataGridView3.DataSource = model3s; 123 dataGridView4.DataSource = model4s.ToList(); ; 124 } 125 126 private void InitDistinctData() 127 { 128 129 var model1s = new List<TestModel1>(); 130 var model2s = new List<TestModel2>(); 131 var model3s = new List<TestModel3>(); 132 for (int i = 0; i < 3; i++) 133 { 134 var model1 = new TestModel1() 135 { 136 Id = 10001, 137 Name = "张三", 138 Address = "中国-上海" 139 }; 140 var model2 = new TestModel2() 141 { 142 Id = 10001, 143 Name = "张三", 144 Address = "中国-上海" 145 }; 146 var model3 = new TestModel3() 147 { 148 Id = 10001, 149 Name = "张三", 150 Address = "中国-上海" 151 }; 152 model1s.Add(model1); 153 model2s.Add(model2); 154 model3s.Add(model3); 155 } 156 157 for (int i = 0; i < 3; i++) 158 { 159 var model1 = new TestModel1() 160 { 161 Id = 10002, 162 Name = "张三", 163 Address = "中国-上海" 164 }; 165 var model2 = new TestModel2() 166 { 167 Id = 10002, 168 Name = "张三", 169 Address = "中国-上海" 170 }; 171 var model3 = new TestModel3() 172 { 173 Id = 10002, 174 Name = "张三", 175 Address = "中国-上海" 176 }; 177 model1s.Add(model1); 178 model2s.Add(model2); 179 model3s.Add(model3); 180 } 181 for (int i = 0; i < 3; i++) 182 { 183 var model1 = new TestModel1() 184 { 185 Id = 10001, 186 Name = "李四", 187 Address = "中国-上海" 188 }; 189 var model2 = new TestModel2() 190 { 191 Id = 10001, 192 Name = "李四", 193 Address = "中国-上海" 194 }; 195 var model3 = new TestModel3() 196 { 197 Id = 10001, 198 Name = "李四", 199 Address = "中国-上海" 200 }; 201 model1s.Add(model1); 202 model2s.Add(model2); 203 model3s.Add(model3); 204 } 205 for (int i = 0; i < 3; i++) 206 { 207 var model1 = new TestModel1() 208 { 209 Id = 10002, 210 Name = "李四", 211 Address = "中国-上海" 212 }; 213 var model2 = new TestModel2() 214 { 215 Id = 10002, 216 Name = "李四", 217 Address = "中国-上海" 218 }; 219 var model3 = new TestModel3() 220 { 221 Id = 10002, 222 Name = "李四", 223 Address = "中国-上海" 224 }; 225 model1s.Add(model1); 226 model2s.Add(model2); 227 model3s.Add(model3); 228 } 229 var model4s = (from m in model1s 230 select new 231 { 232 Id = m.Id, 233 Name = m.Name, 234 Address = m.Address 235 }).ToList().Distinct(); 236 dataGridView1.DataSource = model1s.Distinct().ToList(); 237 dataGridView2.DataSource = model2s.Distinct().ToList(); 238 dataGridView3.DataSource = model3s.Distinct(new ListTestModel3()).ToList(); 239 dataGridView4.DataSource = model4s.ToList(); 240 } 241 242 private void button1_Click(object sender, EventArgs e) 243 { 244 InitDistinctData(); 245 246 }
过滤前结果:
过滤后结果:
分析:model1不管过滤前和过滤后均没有去重,model2 重写了Equals 和GetHashCode两个方法,过滤前后结果不一样, model3实现了IEqualityComparer接口进行了Distinct时重写Equals 和GetHashCode两个方法。效果和model2是一样的。Model4,去重之前用的是自己定义的实体类,框架不知道相等的条件,顾虽然去重但是没有效果,过滤后Model4采用了匿名方法类,简单的匿名类型内部实际是键值对,框架内部使用默认的相等比较器对值进行比较,所以可以去重。
结论:自定义类无法实现多键值去重(Distinct),可以通过以上三种方法去实现。