Как я могу найти определенный элемент в списке <T>? - PullRequest
99 голосов
/ 24 марта 2012

Мое приложение использует такой список:

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

Используя метод Add, в список добавляется еще один экземпляр MyClass.

MyClass предоставляет, среди прочего, следующие методы:

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

Как найти конкретный экземпляр MyClass с помощью метода GetId? Я знаю, что есть метод Find, но я не знаю, сработает ли он здесь?!

Ответы [ 8 ]

223 голосов
/ 24 марта 2012

Используйте лямбда-выражение

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

Примечание: C # имеет встроенный синтаксис для свойств. Вместо написания методов получения и установки (как вы могли бы привыкнуть к Java), напишите

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

value - это контекстное ключевое слово, известное только в наборе доступа. Он представляет значение, присвоенное свойству.

Поскольку этот шаблон часто используется, C # предоставляет автоматически реализуемые свойства . Это краткая версия кода выше; однако вспомогательная переменная скрыта и недоступна (однако она доступна из класса в 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 и переопределить их в производных классах, что позволяет вам предоставлять различные реализации для методов получения и установки; так же, как для обычных виртуальных методов.


Начиная с C # 6.0 (Visual Studio 2015, Roslyn), вы можете писать авто-свойства только для получателя с помощью встроенного инициализатора

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

Вместо этого вы можете инициализировать свойства только для получения в конструкторе. Авто-свойства только для получателя: true свойства только для чтения, в отличие от автоматически реализуемых свойств с частным установщиком.

Это также работает с автоматическими свойствами чтения-записи:

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 ("Roslyn")
Новые функции языка в C # 6

Начиная с C # 7.0 , оба, getter и setter, могут быть записаны с телами выражений:

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

Обратите внимание, что в этом случае установщик должен быть выражением. Это не может быть утверждение. Приведенный выше пример работает, потому что в C # присваивание может использоваться как выражение или как выражение. Значением выражения присваивания является присвоенное значение, где само присвоение является побочным эффектом. Это позволяет вам присвоить значение более чем одной переменной одновременно: x = y = z = 0 эквивалентно x = (y = (z = 0)) и имеет тот же эффект, что и операторы x = 0; y = 0; z = 0;.

17 голосов
/ 24 марта 2012
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();
9 голосов
/ 24 марта 2012

Попробуйте:

 list.Find(item => item.id==myid);
4 голосов
/ 24 марта 2012

Или, если вы не предпочитаете использовать 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
    }
}
4 голосов
/ 24 марта 2012

Вы также можете использовать LINQ расширения:

string id = "hello";
MyClass result = list.Where(m => m.GetId() == id).First();
3 голосов
/ 24 марта 2012

Вы можете максимально кратко решить свою проблему с помощью предиката, написанного с использованием синтаксиса анонимного метода:

MyClass found = list.Find(item => item.GetID() == ID);
0 голосов
/ 20 сентября 2018

Вы можете создать переменную поиска для хранения ваших критериев поиска. Вот пример использования базы данных.

 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» выбирает данные, соответствующие заданным критериям. Не стесняйтесь спрашивать, если у вас есть проблемы с пониманием.

0 голосов
/ 20 июня 2018
public List<DealsCategory> DealCategory { get; set; }
int categoryid = Convert.ToInt16(dealsModel.DealCategory.Select(x => x.Id));
...