2012-03-24 7 views
70

Moja aplikacja używa listę tak:Jak znaleźć konkretny element na liście <T>?

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

Stosując metodę Add kolejna instancja MyClass zostanie dodany do listy.

MyClass przewiduje, między innymi, następujących metod:

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

Jak mogę znaleźć konkretną instancję MyClass poprzez zastosowanie metody GetId? Wiem, że jest metoda Find, ale nie wiem, czy to by tu zadziałało ?!

Odpowiedz

172

użycie wyrażenia lambda

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

Uwaga: C# posiada wbudowany w składni właściwości. Zamiast pisać SEt- i GET metod, pisać

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

value jest kluczowe kontekstowa znane tylko w zbiorze akcesor. Reprezentuje wartość przypisaną do właściwości.

Ponieważ ten wzór jest często używany, C# zapewnia automatycznie zaimplementowane właściwości. Są krótką wersją powyższego kodu; jednak zmienna zabezpieczająca jest ukryta i niedostępna (jest jednak dostępna z klasy w VB).

public string Id { get; set; } 

można po prostu użyć właściwości jakbyś dostępu pole:

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

Użycie właściwości, należy szukać pozycji na liście jak ten

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

Możesz także użyć automatycznie zaimplementowanego Właściwości jeśli trzeba tylko do odczytu właściwość:

public string Id { get; private set; } 

Umożliwia to ustawienie Id obrębie klasy, ale nie z zewnątrz. Jeśli potrzebujesz, aby ustawić go w klasach pochodnych, jak również można również chronić ustawiająca

public string Id { get; protected set; } 

I wreszcie, można zadeklarować właściwości jak virtual i zastąpić je przy wyprowadzaniu klasy, co pozwala zapewnić różne implementacje dla pobierające i ustawiające; podobnie jak w przypadku zwykłych wirtualnych metod.


Od C# 6.0 (Visual Studio 2015, Roslyn) można pisać tylko getter-auto-properties z inicjatora inline

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

Można również zainicjować właściwości getter tylko wewnątrz konstruktora zamiast. Właściwości automatyczne tylko dla gettera są własnością tylko do odczytu, w przeciwieństwie do właściwości zaimplementowanych automatycznie z prywatnym ustawiaczem.

ta współpracuje również z odczytu auto-properties:

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

Począwszy C# 6.0 można również napisać właściwości jak ekspresyjnych treściwe członków

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

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

Począwszy C# 7.0, zarówno, getter i setter, mogą być zapisywane z organami ekspresyjnych:

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

Należy zauważyć, że w tym przypadku rozgrywający musi być wyrażeniem. To nie może być stwierdzenie. Powyższy przykład działa, ponieważ w języku C# przypisanie może być używane jako wyrażenie lub instrukcja. Wartość wyrażenia przypisania jest przypisaną wartością, gdy samo przypisanie jest efektem ubocznym. Umożliwia to przypisanie wartości do więcej niż jednej zmiennej naraz: x = y = z = 0 jest odpowiednikiem x = (y = (z = 0)) i ma taki sam efekt jak instrukcje x = 0; y = 0; z = 0;.

+2

Wielką odpowiedź, dzięki. Dla operacji db wyglądałoby to tak: 'IQueryable result = db.Set () .Find (// tylko id tutaj //). ToList();' To już wie, że szukasz podstawowego klawisz. Tylko dla informacji. – Edgar

+0

Wiem, że jest to stara odpowiedź, ale oddzieliłbym get i zestaw na różne metody, aby wartość nie została przypadkowo ustawiona podczas porównania. –

+0

@JoelTrauger: Porównanie odczytuje właściwość i dlatego wywołuje tylko pobierający. –

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

lub jeśli jest tylko jeden i chcesz wymusić, że coś takiego SingleOrDefault może być to, co chcesz

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

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

Spróbuj:

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

można rozwiązać problemu najbardziej zwięźle z predykatem zapisanym przy użyciu składni anonimowej metody:

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

Można również użyć LINQ rozszerzenia:

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

lub inne przeciążenie First: 'MyClass result = list.First (m => m.GetId() == id); ' –

3

Albo jeśli nie wolą używać LINQ można to zrobić drogę starej szkoły:

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