2017-11-23 120 views
6

Najpierw wybaczą mi mój angielski, ponieważ nie jest to mój język ojczysty. Mam metodę, która otrzymuje ogólną listę List<T>. to czego chcę, to przejść przez całą listę i móc zaktualizować kolumnę o nazwie Wyeliminowana każdej klasy T i która jest typu boolowskiego, czy jest to możliwe? czy ktoś może mi pomóc.Zaktualizuj konkretną kolumnę listy <T>

To, co mam tak daleko:

// Delete (Change status delete = true) 
public void Delete<T>(List<T> data) 
{  
    if (data != null) 
    { 
     data.ForEach(x => 
     { 
      ... 
     }); 
    }   
} 

Z góry dzięki!

+4

To nie działa, ponieważ metoda jest ogólna i nie zawiera żadnych ograniczeń. Oznacza to, że można go wywołać z dowolnym obiektem, nawet z tymi, które nie mają właściwości "Wyeliminowane" lub "Usunięte". –

+0

Czy chcesz ogólnej metody, aby umożliwić aktualizację określonych właściwości? – DavidG

+0

Zastanowiłabym się, czy twoje wiele klas dziedziczy interfejs współdzielony i używają 'List ' zamiast 'List '. –

Odpowiedz

11

Zamiast T używałbym interfejsu, ponieważ w przeciwnym wypadku w foreach nie można uzyskać dostępu do właściwości Eliminated.

Tutaj interfejs:

interface IExample { 

    bool IsEliminated { get; set; }  

} 

i tu metoda z pętlą ForEach.

public void Delete<T>(List<T> data) where T : IExample 
{  
    if (data != null) 
    { 
     data.ForEach(x => 
     { 
      x.Eliminated = true; 
     }); 
    }   
} 
+0

To działa bardzo dobrze dla mnie, dziękuję bardzo! Ostatnie pytanie po wykonaniu tego procesu, jak mogę zaktualizować moją tabelę w bazie danych za pomocą prostego 'ContextDb.SaveChange();' –

+0

np.możesz to zrobić po każdej iteracji w pętli 'ForEach' - działa to dla małych list. W przeciwnym razie musisz to zrobić po 'forEach', aby był wywoływany tylko raz. –

3

Twój T ma właściwość o nazwie Eliminated. Twój kompilator nie może zagwarantować, że kiedykolwiek użyjesz tej metody, będzie miał tego członka, więc nie możesz go skompilować w ten sposób.

Można umieścić ograniczenie na swoim T który pozwala kompilator aby upewnić się, że właściwość istnieje:

public interface Eliminatable 
{ 
    bool Eliminated { get; set; } 
} 

public void Delete<T>(List<T> data) where T : Eliminatable 
{  
    if (data != null) 
    { 
     data.ForEach(x => { x.Eliminated = true; }); 
    }   
} 

Albo (i niektórzy mogą powiedzieć, że to jest hack) można po prostu zaufać użytkownikom, że będzie w rzeczywistości przekazać coś jako T potwierdzający do wzoru:

public void Delete<T>(List<T> data) 
{  
    if (data != null) 
    { 
     data.ForEach(x => { dynamic d = x; d.Eliminated = true; }); 
    }   
} 

teraz będzie to powiedzie, jeżeli nieruchomość nie ma. W czasie wykonywania. Niemiły. Ale to "działa".

+1

dobry punkt z 'dynamicznym' ale normalnie nie sugerowałbym go używać, ponieważ stracisz dużo bezpieczeństwa typu będzie wykonywać. –

+1

@KevinWallis Tak, jestem jednym z tych, którzy uważają to za "hack". Ale to opcja. – nvoigt

4

Jeśli chcesz sposób ogólny, aby zaktualizować listę dowolny typu, można zrobić coś takiego:

public void Update<T>(List<T> data, Action<T> func) 
{ 
    if (data == null) 
     throw new ArgumentNullException(nameof(data)); 

    data.ForEach(func); 
} 

Uwaga mam zmienić czek zerowej rzucać jeśli przejdą w null lista. Możesz po prostu wrócić tutaj, w ten sposób eliminując niektóre zagnieżdżenia.

Umożliwia to przekazanie akcji, która ma zastosowanie do każdego przedmiotu w kolekcji. Można go użyć w następujący sposób:

var data = new List<YourClass> = GetData(); 

Update(data, item => item.Eliminated = true); 
+4

I teraz zastanawiam się, dlaczego nie po prostu: 'foreach (var x in data) x.Eliminated = true;' i zapisz dużo kodu. Jaka jest wartość dodana tego (i innych odpowiedzi)? –

+0

To działa bardzo dobrze dla mnie, dziękuję bardzo! Ostatnie pytanie po wykonaniu tego procesu, jak mogę zaktualizować moją tabelę w mojej bazie danych za pomocą prostego 'ContextDb.SaveChange();' –

+0

@ JonathanBurgosGio Właśnie nazywasz 'SaveChanges', tak jak normalnie. – DavidG