【问题标题】:How to check if an object already exists in list of objects using C#如何使用C#检查对象列表中是否已存在对象
【发布时间】:2018-01-06 03:01:42
【问题描述】:

我想将classStudents 添加到列表_ClassStudents 中,前提是classStudents 尚未在列表中。

public class ClassStudents{

   public Id {get; set;}
   public Name {get; set;}
   public List<Student> Student {get; set;}

}



public static List<ClassStudents> _ClassStudentsList = new List<ClassStudents>();

  public static void addClassStudents(ClassStudents classStudents)
  {
          //if( classStudents isn't in ClassStudentsList ) <------
           _ClassStudentsList.Add(classStudents);
   }

我该怎么做?

【问题讨论】:

  • 如果turma 是一种类型(用户类),则遵循约定使用大写(又名PascalCase),以便将其与变量/字段名称turmas 区分开来。 addTurma 对代码和问题也是多余的。
  • 价值呢,能不一样吗?
  • 'numericUpDown1.Value' 可以有任何向上 0 的数字,但它可以在列表中重复

标签: c#


【解决方案1】:

我认为正确的方法是告诉程序两个Turma 类型相等意味着什么。

public class ClassStudents
{
    public string Name { get; set; }
    public int Value { get; set; }
    // Override the equality operation to check for text value only
    public override bool Equals(object obj)
    {
        if (obj is ClassStudents other) // use pattern matching
        {
            return Name.Equals(other.Name);
        }
        return false;
    }
}

现在您可以使用列表方法.Contains() 来检查项目是否存在。

{
    List<ClassStudents> classStudents = new List<ClassStudents>();

    public Test()
    {
        // Add three values
        classStudents.Add(new ClassStudents() { Name="ABC", Value=101 });
        classStudents.Add(new ClassStudents() { Name="IJK", Value=111 });
        classStudents.Add(new ClassStudents() { Name="XYZ", Value=101 });

        // Check if exists before adding this value
        ClassStudents x = new ClassStudents() { Name="ABC", Value=121 };
        // `Contains()` calls the `Equals()` method of `classStudents`
        if (!classStudents.Contains(x))
        {
            classStudents.Add(x);
        }
    }

}

这会产生最干净的代码,因为检查 if(!classStudents.Contains(x)) 的作用显而易见。此外,您还可以通过向类型添加智能来利用 CLR 的强大功能。 OOP 就是在你的用户类中添加方法来定义动作。在这种情况下,我定义了这种类型的平等意味着什么,现在 CLR 可以在需要的地方使用这些信息。

【讨论】:

  • 虽然你确实提出了一些好的观点,但不应该仅仅为了一个测试而重写 equals。此列表的平等可能并不意味着其他目的的平等,所以我不确定这是否是正确的解决方案。此外,使用 contains 不再比使用 Any 更具可读性。事实上,恰恰相反,因为在 Any 选项中,比较条件就在您面前,您无需猜测 equals 方法是否被覆盖。还有一件事,在覆盖 equals 方法时,您还应该覆盖 GetHashCode 方法。
  • 包含的问题是,当您使用类时,它会查找相同的对象,而不是具有相同值的对象
  • @Mike - 实际上没有。 Contains() 检查内容是否实现 IEquatable 并使用它而不是引用相等。我在发布之前测试了代码。
  • @ja72 我编辑了你的答案,因为我不得不更改我的变量的名称,我正在努力改进我的问题以解除问题
【解决方案2】:

您可以使用Any扩展方法:

var text = nameClassStudents.Text;
if(!_ClassStudentsList.Any(t => t.Text == text))
{
    _ClassStudentsList.Add(new ClassStudents(text,(int)numericUpDown1.Value));
}

但是,这并不能保证名称在列表中是唯一的。 如果您希望得到保证,您可以简单地使用 Dictionary&lt;string, int&gt; 而不是 List&lt;ClassStudents&gt;
字典不允许重复键。
当然,在这里您还需要在向字典添加值之前检查键是否存在:

var dict = new Dictionary<string, int>;
...

var text = nameClassStudents.Text;
if(!dict.ContainsKey(text))
(
    dict.Add(text, (int)numericUpDown1.Value);
)

【讨论】:

  • 这假定每个turma 类型将始终包含两个字段,其中一个是键。将来,您将自己装箱。
  • 是的,你是对的。这是我的假设。但是,使用Dictionary&lt;string, turma&gt; 非常容易,只需使用turma.Name 作为密钥。我以前用过几次的技术。
  • 我有几天试图找到解决方案pt.stackoverflow.com/questions/225116/…
  • 对!,我会尝试查找该项目,如果返回 0 值,则表示该项目不存在
  • @ZoharPeled 我编辑了您的答案,因为必须更改我的变量名称,我正在尝试改进我的问题以解除问题
【解决方案3】:

你也可以使用 HashSet:

public class ClassStudents {

   public Id {get; set;}
   public Name {get; set;}

   public override bool Equals(object obj) {
            return this.Name.Trim().ToLower().Equals(((ClassStudents)obj).Name.Trim().ToLower());
   }

   public override int GetHashCode() {
       return this.Name.GetHashCode();
   }
}

在你的 main() 中,你可以像下面这样声明一个 HashSet:

HashSet <ClassStudents> hash = new HashSet<ClassStudents>();

现在,这将只添加集合中的唯一元素。

【讨论】:

猜你喜欢
  • 2016-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多