在C#中从List<T>获取不同的值

3

大家好,我需要一些关于列表的独特数值,在向列表添加一些数值后。我的代码如下:

             List<Employee_Details> Temp = new List<Employee_Details>();
             Temp =(List<Employee_Details>) newform.Tag;
             EMP_DETAILS.Concat(Temp).Distinct();

但我直接忽略并不添加这些值。

请帮帮我。


变量列表 = (List<Employee_Details>) newform.Tag; 变量去重 = 列表.Distinct()// 变量去重包含不同的值 - Om Deshmane
3个回答

6

Distinct方法要求定义GetHashCodeEquals方法,以便进行对象比较。这些方法可以为类型自身定义,也可以提供一个相应的相等比较器。如果两个对象具有相同的哈希码,则会检查它们是否相等。

您可以为您的类型实现GetHashCodeEquals方法,但是在某些情况下,一个定义的相等性并不适用于所有情况 - 例如,在UI场景中,仅检查两个对象的ID是否匹配可能就足够了,因为UI可能没有对象上可用的所有数据(因此不能始终满足单个真正的相等性)。

因此,我更喜欢为Employee_Details实现IEqualityComparer<T>类型,并将其实例提供给Distinct方法。

public class EmployeeDetailsComparer : IEqualityComparer<Employee_Details>
{
    #region IEqualityComparer<int> Members
    public bool Equals(Employee_Details x, Employee_Details y)
    {
        //define equality
      if(x == null)
      {
        return y == null;
      }
      else if(y == null) return false;
      //now check the fields that define equality - if it's a DB record,
      //most likely an ID field
      return x.ID == y.ID; //this is just A GUESS :)
    }

    public int GetHashCode(Employee_Details obj)
    {
        //define how to get a hashcode
        //most obvious would be to define it on the IDs, 
        //but if equality is defined across multiple fields
        //then one technique is to XOR (^) multiple hash codes together
        //null-check first
        if(obj == null) return 0;
        //now either:
        return obj.ID.GetHashCode();
        //or something like
        return obj.FirstName.GetHashCode() ^ obj.Surname.GetHashCode();
    }

    #endregion
}

现在你可以做到以下几点:
EMP_DETAILS.Concat(Temp).Distinct(new EmployeeDetailsComparer());

需要注意的是,Concat方法实际上不会执行任何操作 - 你需要实际上捕获Concat方法的返回值,可以将其作为IEnumerable<Employee_Details>类型,或将其转换成一个数组或列表:

Employee_Details[] result = 
  EMP_DETAILS.Concat(Temp).Distinct(new EmployeeDetailsComparer()).ToArray();

现在你可以用它来代替 EMP_DETAILS 。如果它是一个 List<Employee_Details> ,你只需要这样做:

EMP_DETAILS = 
  EMP_DETAILS.Concat(Temp).Distinct(new EmployeeDetailsComparer()).ToList();

实际上,在多个值中实现一个良好的哈希码是棘手的,但^方法在大多数情况下都可以工作得很好。目标是确保您获得不同的哈希码,以用于不同的Employee_Details实例。


2
Distinct 方法使用包含对象的 Equals 比较。如果您在 Employee_Details 中使用默认实现的 Equals,则可能会比较引用。
因此,您有两个选择:
  1. 为您的 Employee_Details 实现 Equals 方法。
  2. 使用重载的 Distinct 方法,它接受 IEqualityComparer

不太正确,Distinct 方法使用 GetHashCode 进行相等性比较,如果两个对象具有相同的哈希码,则会进行 Equals 检查。因此,一个良好的实现需要定义这两个方法,可以在类型本身上定义,也可以通过 IEqualityComparer<T> 定义。 - Andras Zoltan
Comparer类有自己的GetHashCode方法。http://msdn.microsoft.com/zh-cn/library/ms132151.aspx - Sly
是的 - 但反编译它并查看它的操作。它只是延迟到 object.GetHashCode,对于自定义类型来说几乎没有用处。 - Andras Zoltan
默认比较器 - 也许,但如果你自己实现它,你不能把任何东西放在那里吗?.. - Sly
是的,抱歉,你可以 - 所以你可以在类型本身上定义 GetHashCode 方法,这可能非常合适。正如我在答案中所说的那样,有时在整个类型范围内定义通用的相等性和哈希码并不总是在其他情况下有效。特别是如果该对象来自数据库,并且并非所有数据在所有情况下都加载。这就是为什么我个人更喜欢专用的 IEqualityComparer<T> 来完成这项工作的原因。但是,是的,如果可以始终保证类型的相等性可以确定,则在类型本身上定义它更有意义。 - Andras Zoltan

2
你需要在你的类中实现 IEqualityComparer<T> 接口,并提供自己的 GetHashCodeEquals 方法。
参考链接:http://msdn.microsoft.com/en-us/library/ms132040.aspx
class Employee_Details : IEqualityComparer
{
    public int Employee_ID;

    public Employee_Details(int empID)
    {
        Employee_ID = empID;
    }

    public new bool Equals(object x, object y)
    {
        return x.ToString().Equals(y.ToString());
    }

    public int GetHashCode(object obj)
    {
        return obj.ToString().ToLower().GetHashCode();
    }

    public override String ToString()
    {
        return Employee_ID.ToString();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接