Bagaimana saya bisa menemukan elemen tertentu dalam Daftar <T>?

114

Aplikasi saya menggunakan daftar seperti ini:

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

Dengan menggunakan Addmetode ini, contoh lain MyClassditambahkan ke daftar.

MyClass menyediakan, antara lain, metode berikut:

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

Bagaimana saya bisa menemukan contoh tertentu MyClassdengan menggunakan GetIdmetode ini? Saya tahu ada Findmetodenya, tapi saya tidak tahu apakah ini akan berhasil di sini ?!

Robert Strauch
sumber

Jawaban:

263

Gunakan ekspresi lambda

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

Catatan: C # memiliki sintaks bawaan untuk properti. Alih-alih menulis metode pengambil dan penyetel (karena Anda mungkin terbiasa dari Java), tulis

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

valueadalah kata kunci kontekstual yang hanya diketahui di set accessor. Ini mewakili nilai yang diberikan ke properti.

Karena pola ini sering digunakan, C # menyediakan properti yang diimplementasikan secara otomatis . Mereka adalah versi singkat dari kode di atas; bagaimanapun, variabel pendukung disembunyikan dan tidak dapat diakses (namun dapat diakses dari dalam kelas di VB).

public string Id { get; set; }

Anda cukup menggunakan properti seolah-olah Anda sedang mengakses bidang:

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

Dengan menggunakan properti, Anda akan mencari item dalam daftar seperti ini

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

Anda juga dapat menggunakan properti yang diimplementasikan secara otomatis jika Anda membutuhkan properti hanya-baca:

public string Id { get; private set; }

Ini memungkinkan Anda untuk mengatur di Iddalam kelas tetapi tidak dari luar. Jika Anda perlu menyetelnya di kelas turunan juga, Anda juga bisa melindungi penyetel

public string Id { get; protected set; }

Dan terakhir, Anda bisa mendeklarasikan properti sebagai virtualdan menimpanya dalam kelas turunan, memungkinkan Anda menyediakan implementasi yang berbeda untuk getter dan setter; seperti untuk metode virtual biasa.


Sejak C # 6.0 (Visual Studio 2015, Roslyn) Anda dapat menulis properti otomatis getter saja dengan inline inisialisasi

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

Anda juga bisa menginisialisasi properti getter-only dalam konstruktor. Properti otomatis khusus pengambil adalah properti hanya baca yang sebenarnya , tidak seperti properti yang diterapkan secara otomatis dengan penyetel pribadi.

Ini juga berfungsi dengan properti otomatis baca-tulis:

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

Mulai dengan C # 6.0 Anda juga dapat menulis properti sebagai anggota bertubuh ekspresi

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

Lihat: .NET Compiler Platform ("Roslyn")
         Fitur Bahasa Baru di C # 6

Dimulai dengan C # 7.0 , keduanya, pengambil dan penyetel, dapat ditulis dengan badan ekspresi:

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

Perhatikan bahwa dalam kasus ini penyetel harus berupa ekspresi. Itu tidak bisa menjadi pernyataan. Contoh di atas berfungsi, karena dalam C # sebuah tugas dapat digunakan sebagai ekspresi atau sebagai pernyataan. Nilai ekspresi tugas adalah nilai yang ditetapkan di mana tugas itu sendiri merupakan efek samping. Ini memungkinkan Anda untuk menetapkan nilai ke lebih dari satu variabel sekaligus: x = y = z = 0setara dengan x = (y = (z = 0))dan memiliki efek yang sama seperti pernyataan x = 0; y = 0; z = 0;.

Versi bahasa berikutnya, C # 9.0, mungkin tersedia pada November 2020, akan memungkinkan properti read-only (atau lebih baik menginisialisasi-sekali) yang dapat Anda inisialisasi di object initializer. Saat ini ini tidak dapat dilakukan dengan properti khusus pengambil.

public string Name { get; init; }

var c = new C { Name = "c-sharp" };
Olivier Jacot-Descombes
sumber
2
Jawaban bagus, terima kasih. Untuk operasi db akan terlihat seperti ini: IQueryable<T> result = db.Set<T>().Find(//just id here//).ToList();Ia sudah tahu bahwa Anda mencari kunci utama. Sekadar info.
Tn. Blond
Saya tahu ini adalah jawaban lama, tetapi saya akan memisahkan get dan set ke dalam metode yang berbeda sehingga nilainya tidak ditetapkan secara tidak sengaja selama perbandingan.
Joel Trauger
@JoelTrauger: Perbandingan membaca properti dan oleh karena itu hanya memanggil pengambil.
Olivier Jacot-Descombes
Ini benar, tetapi tugas yang tidak disengaja akan memanggil penyetel dan memodifikasi properti. Lihat return object.property = valuevsreturn object.property == value
Joel Trauger
Panggilan tak disengaja dari metode set terpisah akan mengubah properti juga. Saya tidak melihat bagaimana metode set terpisah dapat meningkatkan keamanan.
Olivier Jacot-Descombes
19
var list = new List<MyClass>();
var item = list.Find( x => x.GetId() == "TARGET_ID" );

atau jika hanya ada satu dan Anda ingin memaksakan sesuatu seperti SingleOrDefaultyang Anda inginkan

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

if ( item == null )
    throw new Exception();
zellio
sumber
Mengapa Anda menggunakan singleOrDefault jika Anda ingin membuang pengecualian, Gunakan Single ()
Nama Kode Jack
10

Mencoba:

 list.Find(item => item.id==myid);
Amritpal Singh
sumber
6

Atau jika Anda tidak lebih suka menggunakan LINQ, Anda dapat melakukannya dengan cara jadul:

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
    }
}
Bjørn
sumber
4

Anda juga dapat menggunakan ekstensi LINQ :

string id = "hello";
MyClass result = list.Where(m => m.GetId() == id).First();
Guffa
sumber
4
atau kelebihan lain dari First:MyClass result = list.First(m => m.GetId() == id);
Marcel Gosselin
3

Anda dapat menyelesaikan masalah Anda paling singkat dengan predikat yang ditulis menggunakan sintaks metode anonim:

MyClass found = list.Find(item => item.GetID() == ID);
David Heffernan
sumber
0
public List<DealsCategory> DealCategory { get; set; }
int categoryid = Convert.ToInt16(dealsModel.DealCategory.Select(x => x.Id));
Muhammad Armaghan
sumber
Meskipun kode ini dapat menjawab pertanyaan, lebih baik menjelaskan cara menyelesaikan masalah dan memberikan kode sebagai contoh atau referensi. Jawaban kode-saja dapat membingungkan dan tidak memiliki konteks.
Robert Columbia
0

Anda dapat membuat variabel pencarian untuk menampung kriteria pencarian Anda. Berikut ini contoh penggunaan database.

 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

Di sini "kueri var" menghasilkan kriteria pencarian yang Anda berikan melalui variabel pencarian. Kemudian "DuePaymentstring.Select" memilih data yang cocok dengan kriteria Anda. Jangan ragu untuk bertanya jika Anda memiliki masalah pemahaman.

Khandkar Asif Hossain
sumber