2012-03-24 19 views
70

Mi aplicación utiliza una lista como esta:¿Cómo puedo encontrar un elemento específico en una lista <T>?

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

Utilizando el método Add, se añade otra instancia de MyClass a la lista.

MyClass proporciona, entre otros, los siguientes métodos:

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

¿Cómo puedo encontrar una instancia específica de MyClass por medio del uso del método GetId? Sé que existe el método Find, pero no sé si esto funcionaría aquí?

Respuesta

172

utilizar una expresión lambda

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

Nota: C# tiene un sistema incorporado en la sintaxis de propiedades. En lugar de escribir y Set-Get-métodos, escribir

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

value es una palabra clave contextual conocido sólo en el acceso set. Representa el valor asignado a la propiedad.

Dado que este patrón se usa a menudo, C# proporciona propiedades implementadas automáticamente. Son una versión corta del código anterior; sin embargo, la variable de respaldo está oculta y no es accesible (se puede acceder desde dentro de la clase en VB, sin embargo).

public string Id { get; set; } 

Usted puede simplemente utilizar las propiedades como si estuviera accediendo a 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. 

Utilización de las propiedades, que sería buscar elementos en la lista como esta

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

También puede utilizar implementado automáticamente propiedades si necesita una propiedad de sólo lectura:

public string Id { get; private set; } 

Esto le permite establecer la Id dentro de la clase, pero no desde fuera. Si es necesario establecer que en las clases derivadas, así también se puede proteger el colocador

public string Id { get; protected set; } 

Y, por último, se puede declarar propiedades como virtual y anularlos en la obtención de las clases, que le permite ofrecer diferentes implementaciones para getters y setters; al igual que para los métodos virtuales ordinarios.


Desde C# 6.0 (Visual Studio 2015, Roslyn) se puede escribir getter sólo auto-propiedades con un inicializador línea

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

También puede inicializar propiedades de captador de sólo dentro del constructor en su lugar. Las propiedades automáticas solo de Getter son verdaderas propiedades de solo lectura, a diferencia de las propiedades implementadas automáticamente con un setter privado.

Esto funciona también con la lectura y escritura de auto-properties:

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

Empezando con C# 6.0 también se puede escribir propiedades como miembros de expresión cuerpo

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

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

A partir de C# 7.0, ambos, get y set, se puede escribir con los órganos de expresión:

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

Tenga en cuenta que en este caso el colocador debe ser una expresión. No puede ser una declaración. El ejemplo anterior funciona, porque en C#, una asignación se puede usar como una expresión o como una declaración. El valor de una expresión de asignación es el valor asignado donde la asignación en sí es un efecto secundario. Esto le permite asignar un valor a más de una variable a la vez: x = y = z = 0 es equivalente a x = (y = (z = 0)) y tiene el mismo efecto que las declaraciones x = 0; y = 0; z = 0;.

+2

Gran respuesta, gracias. Para el funcionamiento db se vería algo como esto: 'IQueryable result = db.Set () .Find (// solo id aquí //). ToList();' Ya sabría que está buscando primario llave. Sólo por información. – Edgar

+0

Sé que esta es una respuesta anterior, pero separaría el get y establecería en diferentes métodos para que el valor no se establezca accidentalmente durante una comparación. –

+0

@JoelTrauger: una comparación lee la propiedad y, por lo tanto, solo llama al getter. –

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

o si sólo hay una y que desea cumplir que algo como SingleOrDefault puede ser lo que quiere

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

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

Probar:

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

Usted puede resolver su problema más concisa con un predicado escrito usando la sintaxis del método anónimo:

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

También puede utilizar LINQ extensiones:

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

o la otra sobrecarga de Primero: 'MyClass result = list.First (m => m.GetId() == id); ' –

3

O si no prefiere utilizar LINQ se puede hacer de la manera de la vieja escuela:

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