web-dev-qa-db-fra.com

Comment trouver un élément spécifique dans une liste <T>?

Mon application utilise une liste comme celle-ci:

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

En utilisant la méthode Add, une autre instance de MyClass est ajoutée à la liste.

MyClass fournit, entre autres, les méthodes suivantes:

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

Comment trouver une instance spécifique de MyClass en utilisant la méthode GetId? Je sais qu'il existe la méthode Find, mais je ne sais pas si cela fonctionnerait ici?!

91
Robert Strauch

Utilisez une expression lambda

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

Remarque: C # a une syntaxe intégrée pour les propriétés. Au lieu d’écrire les méthodes getter et setter (comme vous le savez peut-être depuis Java), écrivez

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

value est un mot clé contextuel connu uniquement dans l'accesseur d'ensemble. Il représente la valeur attribuée à la propriété.

Comme ce modèle est souvent utilisé, C # fournit des propriétés implémentées automatiquement . Ils sont une version courte du code ci-dessus; cependant, la variable de sauvegarde est cachée et non accessible (elle est accessible depuis la classe en VB, cependant).

public string Id { get; set; }

Vous pouvez simplement utiliser les propriétés comme si vous accédiez à un champ:

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

En utilisant les propriétés, vous rechercheriez des éléments dans la liste comme ceci

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

Vous pouvez également utiliser des propriétés implémentées automatiquement si vous avez besoin d'une propriété en lecture seule:

public string Id { get; private set; }

Cela vous permet de définir Id dans la classe mais pas de l'extérieur. Si vous devez également le définir dans des classes dérivées, vous pouvez également protéger le setter.

public string Id { get; protected set; }

Et enfin, vous pouvez déclarer les propriétés en tant que virtual et les remplacer dans les classes dérivées, ce qui vous permet de fournir différentes implémentations pour les getters et les setters; comme pour les méthodes virtuelles ordinaires.


Depuis C # 6.0 (Visual Studio 2015, Roslyn), vous pouvez écrire des propriétés automatiques pour le getter uniquement avec un initialiseur en ligne.

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

Vous pouvez également initialiser des propriétés en lecture seule dans le constructeur. Les propriétés automatiques réservées aux lecteurs sont les propriétés true en lecture seule, contrairement aux propriétés implémentées automatiquement avec un séparateur privé.

Cela fonctionne aussi avec les propriétés automatiques lecture/écriture:

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

Depuis C # 6.0, vous pouvez également écrire des propriétés en tant que membres avec une expression.

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

Voir: .NET Compiler Platform ("Roslyn")
Nouvelles fonctionnalités linguistiques en C # 6

En commençant par C # 7.0 , les deux, getter et setter, peuvent être écrits avec des corps d'expression:

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

Notez que dans ce cas, le setter doit être une expression. Ce ne peut pas être une déclaration. L'exemple ci-dessus fonctionne, car en C #, une affectation peut être utilisée en tant qu'expression ou en tant qu'énoncé. La valeur d'une expression d'affectation est la valeur attribuée, l'affectation étant elle-même un effet secondaire. Cela vous permet d'affecter une valeur à plusieurs variables à la fois: x = y = z = 0 est équivalent à x = (y = (z = 0)) et a le même effet que les instructions x = 0; y = 0; z = 0;.

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

ou s'il n'y en a qu'un et que vous voulez imposer que quelque chose comme SingleOrDefault peut être ce que vous voulez

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

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

Essayer:

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

Vous pouvez également utiliser LINQ extensions:

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

Ou si vous ne préférez pas utiliser LINQ , vous pouvez le faire à l'ancienne:

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

Vous pouvez résoudre votre problème de manière plus concise avec un prédicat écrit à l'aide de la syntaxe de méthode anonyme:

MyClass found = list.Find(item => item.GetID() == ID);
3
David Heffernan
public List<DealsCategory> DealCategory { get; set; }
int categoryid = Convert.ToInt16(dealsModel.DealCategory.Select(x => x.Id));
0
Muhammad Armaghan

Vous pouvez créer une variable de recherche pour contenir vos critères de recherche. Voici un exemple d'utilisation de la base de données.

 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

Ici, "var query" génère les critères de recherche que vous donnez à travers la variable de recherche. Ensuite, "DuePaymentstring.Select" sélectionne les données correspondant à vos critères. N'hésitez pas à demander si vous avez un problème de compréhension. 

0