Poniżej znajduje się wyciąg z mojego kodu:
public class AllIntegerIDs
{
public AllIntegerIDs()
{
m_MessageID = 0;
m_MessageType = 0;
m_ClassID = 0;
m_CategoryID = 0;
m_MessageText = null;
}
~AllIntegerIDs()
{
}
public void SetIntegerValues (int messageID, int messagetype,
int classID, int categoryID)
{
this.m_MessageID = messageID;
this.m_MessageType = messagetype;
this.m_ClassID = classID;
this.m_CategoryID = categoryID;
}
public string m_MessageText;
public int m_MessageID;
public int m_MessageType;
public int m_ClassID;
public int m_CategoryID;
}
Próbuję użyć następującego kodu w moim kodzie funkcji main ():
List<AllIntegerIDs> integerList = new List<AllIntegerIDs>();
/* some code here that is ised for following assignments*/
{
integerList.Add(new AllIntegerIDs());
index++;
integerList[index].m_MessageID = (int)IntegerIDsSubstring[IntOffset];
integerList[index].m_MessageType = (int)IntegerIDsSubstring[IntOffset + 1];
integerList[index].m_ClassID = (int)IntegerIDsSubstring[IntOffset + 2];
integerList[index].m_CategoryID = (int)IntegerIDsSubstring[IntOffset + 3];
integerList[index].m_MessageText = MessageTextSubstring;
}
Problem jest tutaj: próbuję wydrukować wszystkie elementy z mojej listy przy użyciu pętli for:
for (int cnt3 = 0 ; cnt3 <= integerList.FindLastIndex ; cnt3++) //<----PROBLEM HERE
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\n", integerList[cnt3].m_MessageID,integerList[cnt3].m_MessageType,integerList[cnt3].m_ClassID,integerList[cnt3].m_CategoryID, integerList[cnt3].m_MessageText);
}
Chcę znaleźć ostatni element, aby zrównać cnt3 w mojej pętli for i wydrukować wszystkie wpisy na liście. Każdy element listy jest obiektem klasy AllIntegerIDs, jak wspomniano powyżej w przykładowym kodzie. Jak znaleźć ostatni ważny wpis na liście?
Czy powinienem użyć czegoś takiego jak integerList.Find (integerList []. M_MessageText == null;
Jeśli go użyję, będzie potrzebny indeks, który będzie w zakresie od 0 do dowolnego maksimum. Znaczy, będę musiał użyć innej pętli for, której nie zamierzam używać. Czy istnieje krótszy / lepszy sposób?
Dzięki, Viren
AllIntegerIDs newItem = new AllIntegerID();
, użyj tego do przypisania wszystkich pól, a następnie zadzwońintegerList.Add(newItem)
. Lub użyj właściwości zamiast pól i użyj składni inicjatora obiektu C # 3.0.Odpowiedzi:
Jeśli chcesz tylko uzyskać dostęp do ostatniej pozycji na liście, możesz to zrobić
aby uzyskać całkowitą liczbę elementów na liście, możesz użyć właściwości Count
źródło
Last
/LastOrDefault
jak wspomniano poniżej.Enumerable.Last
zgłosi wyjątek, jeśli lista jest pusta. Jeśli zadzwoniszEnumerable.LastOrDefault
i przekażesz listę typów wartości, wartość domyślna zostanie zwrócona, jeśli lista jest pusta. Więc jeśli otrzymasz 0 z powrotem z aList<int>
, nie będziesz wiedział, czy lista była pusta, czy też ostatnia wartość wynosiła 0. Krótko mówiąc, musisz sprawdzićCount
mechanizm pobierania, którego zdecydujesz się użyć.var element = list[list.Count - 1]
jest ona bardzo zwięzła i czytelna. Nie ma potrzeby wywoływania metod rozszerzającychAby uzyskać ostatni element kolekcji, użyj metod rozszerzających LastOrDefault () i Last ()
LUB
Pamiętaj, aby dodać
using System.Linq;
, w przeciwnym razie ta metoda nie będzie dostępna.źródło
First
,FirstOrDefault
,Last
,LastOrDefault
,Single
,SingleOrDefault
,ElementAt
iElementAtOrDefault
są zoptymalizowane pod kątemIList<TSource>
,Count
iContains
są zoptymalizowane pod kątemICollection<TSource>
iCast<TResult>
jest zoptymalizowany pod kątemIEnumerable<TResult>
.using System.Linq;
System.Linq.Enumerable
nie są tak naprawdę „zoptymalizowane”. Oto kodEnumerable.Last
metody.System.Linq.Enumerable.Last
, zgadzam się z 0b101010 -Last()
kod nie jest "zoptymalizowany dlaList<>
s" -Last()
jest po prostu brzydkim opakowaniem, które domyślnie jest ustawionereturn list[list.Count-1]
w przypadku, gdy argumentem jestIList
, i iteruje listę do końca w przypadku to nie jest ... co czyni to bardzo słabym rozwiązaniem, jeśliIList
jest aLinkedList
, ponieważ indeksator przejdzie przez całą listę niepotrzebnie (nie znalazłem zastąpienia iterującego wstecz zaItem[]
pomocą index> Count / 2 w źródłach c #, YMMV )Przejdźmy do sedna pytania, jak bezpiecznie zająć się ostatnim elementem listy ...
Zarozumiały
Następnie
„count-1” to zły nawyk, chyba że najpierw zagwarantujesz, że lista nie jest pusta.
Nie ma wygodnego sposobu sprawdzenia pustej listy poza zrobieniem tego.
Najkrótszy sposób, jaki przychodzi mi do głowy, to
możesz pójść na całość i utworzyć delegata, który zawsze zwraca wartość true, i przekazać go do FindLast, który zwróci ostatnią wartość (lub domyślną wartość skonstruowaną, jeśli lista jest pusta). Ta funkcja zaczyna się na końcu listy, więc będzie Wielkie O (1) lub stały czas, mimo że metoda zwykle to O (n).
Metoda FindLast jest brzydka, jeśli policzysz część delegata, ale musi zostać zadeklarowana tylko w jednym miejscu. Jeśli lista jest pusta, zwróci domyślną skonstruowaną wartość typu listy „” dla łańcucha. Pójście dalej z delegatem alwaysTrue, czyniąc go szablonem zamiast typu string, byłoby bardziej przydatne.
źródło
myList.FindLast(_unused_variable_name => true);
będzie działać niezależnie od typu. Jest to krótsza wersjamyList.FindLast(_ => true);
, ale uważam, że tylko podkreślenie (lub dowolny inny identyfikator pojedynczego znaku) może być czasami nieco mylące.źródło
Zmiana
do
źródło
Skorzystaj z
Count
nieruchomości. Ostatni indeks będzieCount - 1
.źródło
Możesz go znaleźć licząc najpierw liczbę elementów na liście, np
Następnie możesz zindeksować liczbę - 1, aby uzyskać ostatni element na liście, np
źródło
W C # 8.0 można uzyskać ostatni element z pełnym wyjaśnieniem operatora ^
źródło
Dlaczego po prostu nie użyć właściwości Count na liście?
źródło
Niezależnie od pierwotnego pytania uzyskasz lepszą wydajność, jeśli będziesz przechwytywać odwołania do zmiennych lokalnych zamiast wielokrotnie indeksować listę:
A w twojej
for
pętli:źródło
Musiałbym się zgodzić, że dla każdego byłoby o wiele łatwiejsze
Sugerowałbym również dodanie właściwości, aby uzyskać dostęp do swoich informacji zamiast pól publicznych, w zależności od wersji .net możesz dodać to jak
public int MessageType {get; set;}
i pozbyć sięm_
z pól publicznych, właściwości itp., Ponieważ nie powinno ich tam być.źródło
Myślę, że to ci pomaga. Proszę sprawdzić
źródło