如何在 List<T> 中找到特定元素?

Posted

技术标签:

【中文标题】如何在 List<T> 中找到特定元素?【英文标题】:How can I find a specific element in a List<T>? 【发布时间】:2012-04-08 22:34:45 【问题描述】:

我的应用程序使用这样的列表:

List&lt;MyClass&gt; list = new List&lt;MyClass&gt;();

使用Add 方法,MyClass 的另一个实例被添加到列表中。

MyClass 提供以下方法:

public void SetId(String Id);
public String GetId();

如何使用GetId 方法找到MyClass 的特定实例?我知道有Find 方法,但我不知道这是否可以在这里工作?!

【问题讨论】:

【参考方案1】:

使用 lambda 表达式

MyClass result = list.Find(x => x.GetId() == "xy");

注意:C# 具有内置的属性语法。不要将 getter 和 setter 写成普通的方法(就像你在 Java 中可能习惯的那样),而是写

private string _id;
public string Id

    get
    
        return _id;
    
    set
    
        _id = value;
    

value 是仅在 set 访问器中已知的上下文关键字。它表示分配给属性的值。

由于经常使用这种模式,C# 提供了auto-implemented properties。它们是上述代码的简短版本;但是,支持变量是隐藏的且不可访问(但是,它可以从 VB 的类中访问)。

public string Id  get; set; 

您可以像访问字段一样简单地使用属性:

var obj = new MyClass();
obj.Id = "xy";       // Calls the setter with "xy" assigned to the value parameter.
string id = obj.Id;  // Calls the getter.

使用属性,您可以像这样在列表中搜索项目

MyClass result = list.Find(x => x.Id == "xy"); 

如果您需要只读属性,也可以使用自动实现的属性:

public string Id  get; private set; 

这使您可以在类内设置Id,但不能从外部设置。如果您还需要在派生类中设置它,您还可以保护设置器

public string Id  get; protected set; 

最后,您可以将属性声明为virtual 并在派生类中覆盖它们,从而允许您为getter 和setter 提供不同的实现;就像普通的虚方法一样。


从 C# 6.0(Visual Studio 2015,Roslyn)开始,您可以使用内联初始化程序编写仅 getter 的自动属性

public string Id  get;  = "A07"; // Evaluated once when object is initialized.

您也可以改为在构造函数中初始化 getter-only 属性。 Getter-only 自动属性是 true 只读属性,与使用私有 setter 的自动实现属性不同。

这也适用于读写自动属性:

public string Id  get; set;  = "A07";

从 C# 6.0 开始,您还可以将属性编写为表达式体成员

public DateTime Yesterday => DateTime.Date.AddDays(-1); // Evaluated at each call.
// Instead of
public DateTime Yesterday  get  return DateTime.Date.AddDays(-1);  

见:.NET Compiler Platform ("Roslyn")New Language Features in C# 6

以C# 7.0 开头,getter 和 setter 都可以写成表达式体:

public string Name

    get => _name;                                // getter
    set => _name = value;                        // setter

请注意,在这种情况下,setter 必须是表达式。它不能是一个声明。上面的示例有效,因为在 C# 中,赋值可以用作表达式或语句。赋值表达式的值是赋值本身是副作用的赋值。这允许您一次为多个变量赋值:x = y = z = 0 等价于 x = (y = (z = 0)),并且与语句 x = 0; y = 0; z = 0; 具有相同的效果。

从 C# 9.0 开始,您可以使用可以在对象初始化程序中初始化的只读(或更好的一次性初始化)属性。目前,只有 getter 的属性无法做到这一点。

public string Name  get; init; 

var c = new C  Name = "c-sharp" ;

讨论了 C# 未来版本的一个特性:field 关键字允许访问自动创建的支持字段。

// Removes time part in setter
public DateTime HiredDate  get; init => field = value.Date(); 

【讨论】:

很好的答案,谢谢。对于 db 操作,它看起来像这样:IQueryable&lt;T&gt; result = db.Set&lt;T&gt;().Find(//just id here//).ToList(); 它已经知道您正在寻找主键。仅供参考。 我知道这是一个旧答案,但我会将 get 和 set 分成不同的方法,以便在比较过程中不会意外设置值。 @JoelTrauger:比较读取属性,因此只调用 getter。 这是真的,但是一个意外的赋值会调用setter并修改属性。请参阅return object.property = valuereturn object.property == value 意外调用单独的 set 方法也会修改属性。我看不出单独的 get set 方法如何提高安全性。【参考方案2】:
var list = new List<MyClass>();
var item = list.Find( x => x.GetId() == "TARGET_ID" );

或者如果只有一个并且您想强制执行 SingleOrDefault 之类的内容可能是您想要的

var item = list.SingleOrDefault( x => x.GetId() == "TARGET" );

if ( item == null )
    throw new Exception();

【讨论】:

如果要抛出异常,为什么要使用singleOrDefault,使用Single()【参考方案3】:

试试:

 list.Find(item => item.id==myid);

【讨论】:

【参考方案4】:

您可以使用使用匿名方法语法编写的谓词最简洁地解决您的问题:

MyClass found = list.Find(item => item.GetID() == ID);

【讨论】:

【参考方案5】:

您也可以使用LINQ 扩展:

string id = "hello";
MyClass result = list.Where(m => m.GetId() == id).First();

【讨论】:

或First的其他重载:MyClass result = list.First(m =&gt; m.GetId() == id); 【参考方案6】:

或者,如果您不喜欢使用 LINQ,您可以使用老式方法:

List<MyClass> list = new List<MyClass>();
foreach (MyClass element in list)

    if (element.GetId() == "heres_where_you_put_what_you_are_looking_for")
    

        break; // If you only want to find the first instance a break here would be best for your application
    

【讨论】:

【参考方案7】:
public List<DealsCategory> DealCategory  get; set; 
int categoryid = Convert.ToInt16(dealsModel.DealCategory.Select(x => x.Id));

【讨论】:

虽然这段代码可以回答问题,但最好解释一下如何解决问题,并提供代码作为示例或参考。仅代码的答案可能会令人困惑且缺乏上下文。【参考方案8】:

您可以创建一个搜索变量来保存您的搜索条件。这是一个使用数据库的示例。

 var query = from o in this.mJDBDataset.Products 
             where o.ProductStatus == textBox1.Text || o.Karrot == textBox1.Text 
             || o.ProductDetails == textBox1.Text || o.DepositDate == textBox1.Text 
             || o.SellDate == textBox1.Text
             select o;

 dataGridView1.DataSource = query.ToList();

 //Search and Calculate
 search = textBox1.Text;
 cnn.Open();
 string query1 = string.Format("select * from Products where ProductStatus='"
               + search +"'");
 SqlDataAdapter da = new SqlDataAdapter(query1, cnn);
 DataSet ds = new DataSet();
 da.Fill(ds, "Products");
 SqlDataReader reader;
 reader = new SqlCommand(query1, cnn).ExecuteReader();

 List<double> DuePayment = new List<double>();

 if (reader.HasRows)
 

  while (reader.Read())
  

   foreach (DataRow row in ds.Tables["Products"].Rows)
   

     DuePaymentstring.Add(row["DuePayment"].ToString());
     DuePayment = DuePaymentstring.Select(x => double.Parse(x)).ToList();

   
  

  tdp = 0;
  tdp = DuePayment.Sum();                        
  DuePaymentstring.Remove(Convert.ToString(DuePaymentstring.Count));
  DuePayment.Clear();
 
 cnn.Close();
 label3.Text = Convert.ToString(tdp + " Due Payment Count: " + 
 DuePayment.Count + " Due Payment string Count: " + DuePaymentstring.Count);
 tdp = 0;
 //DuePaymentstring.RemoveRange(0,DuePaymentstring.Count);
 //DuePayment.RemoveRange(0, DuePayment.Count);
 //Search and Calculate

这里的“var query”正在生成您通过搜索变量提供的搜索条件。然后“DuePaymentstring.Select”正在选择符合您给定条件的数据。随意询问您是否有理解问题。

【讨论】:

以上是关于如何在 List<T> 中找到特定元素?的主要内容,如果未能解决你的问题,请参考以下文章

请教C#中的List<T>,筛选list中特定元素的方法

请教C#中的List<T>,删除list中特定元素的方法

C#List<T>如何找到集合中的最后一个元素?

如何找到具有特定父级的元素?

如何识别 List<T> 是不是是实现特定接口的 T 列表

C#GetType():代码如何在没有实际元素的情况下获取 List<T> 中 T 的类型? [复制]