2012-03-24 5 views
70

La mia applicazione utilizza una lista come questa:Come posso trovare un elemento specifico in un elenco <T>?

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

Utilizzando il metodo Add, un'altra istanza di MyClass viene aggiunto alla lista.

MyClass prevede, tra gli altri, i seguenti metodi:

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

Come posso trovare una specifica istanza di MyClass mediante utilizzando il metodo GetId? So che c'è il metodo Find, ma non so se funzionerebbe qui ?!

risposta

172

usare un'espressione lambda

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

Nota: C# ha un built-in sintassi per proprietà. Invece di scrivere Set-e Get-metodi, scrivere

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

value è una parola chiave contestuale noto solo nel accesso set. Rappresenta il valore assegnato alla proprietà.

Poiché questo modello è spesso utilizzato, C# fornisce proprietà implementate automaticamente. Sono una versione breve del codice sopra; tuttavia, la variabile di supporto è nascosta e non accessibile (tuttavia è accessibile all'interno della classe in VB).

public string Id { get; set; } 

Si può semplicemente utilizzare le proprietà come se si stesse accedendo un campo:

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

Uso delle proprietà, si dovrebbe cercare gli elementi nella lista come questa

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

È anche possibile utilizzare automaticamente implementato proprietà, se avete bisogno di un proprietà di sola lettura:

public string Id { get; private set; } 

Ciò consente di impostare la Id all'interno della classe, ma non dall'esterno. Se è necessario impostare in classi derivate, come ben si può anche proteggere il setter

public string Id { get; protected set; } 

E, infine, è possibile dichiarare le proprietà come virtual e ignorare nel derivare classi, permettendo di fornire implementazioni diverse per getter e setter; proprio come per i metodi virtuali ordinari.


Da C# 6.0 (Visual Studio 2015, Roslyn) è possibile scrivere auto-proprietà getter-solo con un inizializzatore linea

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

È anche possibile inizializzare le proprietà getter-solo all'interno del costruttore, invece. Le proprietà automatiche di solo assorbimento sono true proprietà di sola lettura, diversamente dalle proprietà implementate automaticamente con un setter privato.

Questo funziona anche con lettura-scrittura auto-proprietà:

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

che iniziano con C# 6.0 è possibile anche scrivere le proprietà come membri espressione di corpo

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

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

Partendo C# 7.0, sia, getter e setter, può essere scritto con i corpi di espressione:

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

Si noti che in questo caso il setter deve essere un'espressione. Non può essere una dichiarazione. L'esempio sopra funziona, perché in C#, un compito può essere usato come espressione o come dichiarazione. Il valore di un'espressione di assegnazione è il valore assegnato in cui l'assegnazione stessa è un effetto collaterale. Ciò consente di assegnare un valore a più di una variabile contemporaneamente: x = y = z = 0 equivale a x = (y = (z = 0)) e ha lo stesso effetto delle istruzioni x = 0; y = 0; z = 0;.

+2

Grande risposta, grazie. Per l'operazione db, sarebbe simile a questa: 'IQueryable result = db.Set (). .Find (// solo id qui //). ToList();' Sapresti già che stai cercando chiave. Solo per informazioni – Edgar

+0

So che questa è una vecchia risposta, ma separerei il get e l'impostazione in metodi diversi in modo che il valore non venga impostato per errore durante un confronto. –

+0

@JoelTrauger: un confronto legge la proprietà e pertanto chiama solo il getter. –

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

o se v'è una sola e si desidera far rispettare che qualcosa di simile SingleOrDefault può essere ciò che si desidera

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

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

Prova:

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

È possibile risolvere il problema più conciso con un predicato scritto utilizzando la sintassi del metodo anonimo:

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

È anche possibile utilizzare LINQ estensioni:

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

o l'altro overload di First: 'MyClass result = list.First (m => m.GetId() == id); ' –

3

O se non si preferisce utilizzare LINQ si può fare alla vecchia scuola:

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