List <T> içindeki belirli bir öğeyi nasıl bulabilirim?


114

Uygulamam şöyle bir liste kullanıyor:

List<MyClass> list = new List<MyClass>();

AddYöntemi kullanarak, MyClasslisteye başka bir örnek eklenir.

MyClass diğerleri arasında aşağıdaki yöntemleri sağlar:

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

Yöntemi MyClasskullanarak belirli bir örneğini nasıl bulabilirim GetId? FindYöntem olduğunu biliyorum , ama bunun burada işe yarayıp yaramayacağını bilmiyorum ?!

Yanıtlar:


263

Lambda ifadesi kullanın

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

Not: C #, özellikler için yerleşik bir sözdizimine sahiptir. Alıcı ve ayarlayıcı yöntemleri yazmak yerine (Java'dan alışkın olabileceğiniz gibi),

private string _id;
public string Id
{
    get
    {
        return _id;
    }
    set
    {
        _id = value;
    }
}

valueyalnızca set erişimcisinde bilinen bağlamsal bir anahtar sözcüktür. Özelliğe atanan değeri temsil eder.

Bu desen sıklıkla kullanıldığından, C # otomatik uygulanan özellikler sağlar . Yukarıdaki kodun kısa bir versiyonudur; ancak, destek değişkeni gizlidir ve erişilebilir değildir (ancak VB'deki sınıfın içinden erişilebilir).

public string Id { get; set; }

Özellikleri bir alana erişiyormuş gibi kullanabilirsiniz:

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

Özellikleri kullanarak, listedeki öğeleri şu şekilde ararsınız

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

Salt okunur bir özelliğe ihtiyacınız varsa, otomatik uygulanan özellikleri de kullanabilirsiniz:

public string Id { get; private set; }

Bu Id, sınıf içinde ayarlamanıza olanak tanır , ancak dışarıdan değil. Bunu türetilmiş sınıflarda da ayarlamanız gerekirse, ayarlayıcıyı da koruyabilirsiniz.

public string Id { get; protected set; }

Ve son olarak, virtualsınıfları türetmede özellikleri olarak bildirebilir ve onları geçersiz kılabilir, böylece alıcılar ve ayarlayıcılar için farklı uygulamalar sağlamanıza olanak tanır; sıradan sanal yöntemlerde olduğu gibi.


C # 6.0'dan (Visual Studio 2015, Roslyn) bu yana, satır içi başlatıcıyla yalnızca alıcıya özgü otomatik özellikler yazabilirsiniz

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

Bunun yerine yapıcı içinde yalnızca alıcı özelliklerini de başlatabilirsiniz. Yalnızca alıcı otomatik özellikleri, özel ayarlayıcıya sahip otomatik uygulanan özelliklerin aksine gerçek salt okunur özelliklerdir.

Bu, okuma-yazma otomatik özellikleriyle de çalışır:

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

C # 6.0 ile başlayarak, özellikleri ifade gövdeli üyeler olarak da yazabilirsiniz.

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

Bkz: .NET Derleyici Platformu ("Roslyn")
         C # 6'daki Yeni Dil Özellikleri

C # 7.0 ile başlayarak , hem alıcı hem de ayarlayıcı ifade gövdeleri ile yazılabilir:

public string Name
{
    get => _name;                                // getter
    set => _name = value;                        // setter
}

Bu durumda ayarlayıcının bir ifade olması gerektiğine dikkat edin. Bir ifade olamaz. Yukarıdaki örnek işe yarar, çünkü C # 'da bir atama bir ifade veya bir ifade olarak kullanılabilir. Bir atama ifadesinin değeri, atamanın kendisinin bir yan etki olduğu atanmış değerdir. Bu, aynı anda birden fazla değişkene bir değer atamanıza olanak tanır: x = y = z = 0eşdeğerdir x = (y = (z = 0))ve ifadelerle aynı etkiye sahiptir x = 0; y = 0; z = 0;.

Dilin bir sonraki sürümü olan C # 9.0, muhtemelen Kasım 2020'de kullanıma sunulacak, bir nesne başlatıcıda başlatabileceğiniz salt okunur (veya bir kez daha iyi başlat) özelliklerine izin verecektir. Bu, yalnızca alıcı özellikleriyle şu anda mümkün değildir.

public string Name { get; init; }

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

2
Harika cevap, teşekkürler. Db işlemi için şuna benzer: IQueryable<T> result = db.Set<T>().Find(//just id here//).ToList();Birincil anahtarı aradığınızı zaten bilirdi. Sadece bilgi için.
Bay Blond

Bunun eski bir cevap olduğunu biliyorum, ancak get ve set'i farklı yöntemlere ayırırdım, böylece değer bir karşılaştırma sırasında yanlışlıkla ayarlanmasın.
Joel Trauger

@JoelTrauger: Bir karşılaştırma özelliği okur ve bu nedenle yalnızca alıcıyı çağırır.
Olivier Jacot-Descombes

Bu doğrudur, ancak yanlışlıkla yapılan bir atama ayarlayıcıyı çağırır ve özelliği değiştirir. See return object.property = valuevsreturn object.property == value
Joel Trauger

Ayrı bir küme yönteminin yanlışlıkla çağrılması da özelliği değiştirecektir. Ayrı get set yöntemlerinin güvenliği nasıl artırabileceğini anlamıyorum.
Olivier Jacot-Descombes

19
var list = new List<MyClass>();
var item = list.Find( x => x.GetId() == "TARGET_ID" );

ya da sadece bir tane varsa ve istediğiniz gibi bir SingleOrDefaultşeyin olmasını sağlamak istiyorsanız

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

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

İstisna atmak istiyorsanız neden singleOrDefault kullanıyorsunuz, Tek Kullan ()
Kod Adı Jack


6

Veya LINQ kullanmayı tercih etmezseniz, bunu eski usul yöntemle yapabilirsiniz:

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
    }
}

4

Ayrıca LINQ uzantılarını da kullanabilirsiniz :

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

4
ya da First'ün diğer aşırı yüklemesi:MyClass result = list.First(m => m.GetId() == id);
Marcel Gosselin

3

Anonim yöntem sözdizimi kullanılarak yazılan bir yüklemle probleminizi en kısaca çözebilirsiniz:

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

0
public List<DealsCategory> DealCategory { get; set; }
int categoryid = Convert.ToInt16(dealsModel.DealCategory.Select(x => x.Id));

Bu kod soruyu yanıtlasa da sorunun nasıl çözüleceğini açıklamak ve kodu örnek veya referans olarak sağlamak daha iyidir. Yalnızca kod yanıtları kafa karıştırıcı olabilir ve bağlamdan yoksun olabilir.
Robert Columbia

0

Arama kriterlerinizi tutmak için bir arama değişkeni oluşturabilirsiniz. İşte veritabanı kullanan bir örnek.

 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

Burada "var query", arama değişkeni aracılığıyla verdiğiniz arama kriterlerini oluşturuyor. Ardından "DuePaymentstring.Select", verdiğiniz kriterlere uyan verileri seçer. Anlamakta sorun yaşayıp yaşamadığınızı sormaktan çekinmeyin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.