List<T> - Resize?
-
Was genau willst Du denn jetzt ?! Du wirfst das ein oder andere doch auch durcheinander. Also mal von vorne:
Gibt es bei List<T> keine Resize Funktionalität?
Nein, weder im Sinne von Array.Resize noch im Sinne von std::vector::resize .
Was gibt es da für alternative Möglichkeiten?
Die Möglichkeiten hängen vom Ziel bzw. der Möglichkeiten ab.
Beispiel:
class Test { public override string ToString() { return num.ToString(); } static int count = 0; int num = 0; public Test() { count++; num = count; } } static class Program { static void Main(string[] args) { List<Test> liste = new List<Test>(); liste.Resize(100); for (int i = 0; i < 10; i++) liste[i] = new Test(); liste.Resize(10); } static void Resize<T>(this List<T> liste,Int32 count) { if (liste.Count == count) return; if(liste.Count < count) liste.AddRange(new T[count-liste.Count]); else { liste.RemoveRange(count, liste.Count - count); liste.TrimExcess(); } } }
Du kannst auch einen Delegaten abverlangen der neue Objekte erstellt, ein Objekt mit übergeben lassen und dies hinzufügen (Wobei dann geregelt werden muss ob nur die Referenz aufgenommen werden soll oder eine Kopie) etc.
Will ich nicht! Lesen hier eigentlich alle nur, was sie lesen wollen?
Ja und nein. Man liest die Frage und wegt den Nutzen gegenüber dem Framework ab. Das Resize ist an sich nur vom Array bekannt und wird meist auch nur dort verwendet. Das erwähnen Array.Resize hat dann sein übriges getan um für Chaos zu sorgen.
Kurz:
Nein, die Funktionalität gibt es nicht. Die Möglichkeiten hängen von der konkreten Aufgabe ab.
Bereits schon getan, allerdings wundert es mich eben, dass List<T> sowas nicht bereits selber aufweist
Wurde ebenfalls beantwortet. Du reagierst auf solche Antworten aber stehts nur mit einem "Ihr versteht nicht was ich will".
-
@Knuddlbaer,
Perfekt, danke! Es geht doch
Ich werde das nächste Mal probieren ein wenig anders zu erklären, was ich will. Vielleicht bin ich auch immer noch zu sehr von C++ beeinflusst, wodurch meine Erklärungen für Verwirrung stifteten ...Knuddlbaer schrieb:
Bereits schon getan, allerdings wundert es mich eben, dass List<T> sowas nicht bereits selber aufweist
Wurde ebenfalls beantwortet. Du reagierst auf solche Antworten aber stehts nur mit einem "Ihr versteht nicht was ich will".
Wenn du genau hinschaust, wirst du feststellen, dass ich da gar kein Fragezeichen hinzugeschrieben habe. Und die Antworten darauf waren bisher mehr von der Art:
- Wenn du das willst, dann hast du einen Designfehler.
- Es soll nicht alles ins Interface rein.
- Es gibt zu wenig Anwendungsfälle.
...
Allerdings waren alle Aussagen ohne Begründung, wieso es denn so ist. Oder dann wurde ich wirklich falsch verstanden. Zwergli hat zum Beispiel darauf argumentiert, dass ich den Speicher vonList<T>
selber verwalten möchte, was aber nicht der Fall ist.Naja, dann wundert es mich halt weiterhin, hauptsache ich weiss nun definitiv, dass es nichts in der Art schon gibt und ich selber für eine Lösung sorgen muss.
Grüssli
-
Das Thema scheint ja jetzt gegessen, aber eins muss ich noch loswerden
Dravere schrieb:
Zwergli hat zum Beispiel darauf argumentiert, dass ich den Speicher von
List<T>
selber verwalten möchte, was aber nicht der Fall ist.Nein, da hast du dir meine Argumentation zurechtgebogen, so dass sie besser passt
Das habe ich nicht gesagt, aber in der Art hast du ja einige Aussagen verdreht.
Ich habe gesagt dass ein Resize bei einer List, wenn es so wie bei einem Array durchgeführt wird, in die Wachstumsstategie der List eingreift und man damit praktisch den internen Speicher der List selber verwaltet.
Achte drauf das die Kausalität umgedreht ist zu deiner Aussage. Ich habe nicht gesagt dass du manuell den Speicher der List verwalten willst, sondern dass ein Resizen der List dem manuellen verwalten des Speichers gleicht, da die List normalerweise selber wächst.
-
@Zwergli,
Kommt darauf an, was man alles zu Funktionalität vonArray.Resize
nimmt oder als Implementationsdetail sieht.
Als Funktionalität sehe ich, dass ich ein Array übergebe und danach in dieser Variable ein Array neuer Grösse habe. Falls es grösser ist, dann sind die neuen Elemente mit einem Defaultwert odernull
initialisiert.
Dass dies ein neues Array sein kann, welches frisch angelegt wurde, sehe ich als Implementationsdetail.Womöglich kam daher die Verwirrung, wobei ich allerdings dachte, dass dies klar sein würde, denn alles andere macht, wie du es bereits festgestellt hast, überhaupt gar keinen Sinn. Auch habe ich mehrmals gesagt, dass ich nur die Anzahl Element verändern will und den internen Speicher nicht anfassen möchte, bzw. dass dieser mir scheiss egal ist und ich der Verwaltung von
List<T>
nicht reinpfuschen will. Ich habe sogar ein Beispiel präsentiert, was ich meine, wo es schön mehrmalsAdd
, bzw.Remove
aufruft. Auchstd::vector::resize
zeigt wunderbar auf, was ich möchte, denn dabei wird intern auch kein neues Array angelegt, wenn der Speicher reicht.
Sag mir, wie ich das noch deutlicher hätte sagen sollen?Und deine Argumentation ist daher eben falsch, weil sie sich auf etwas bezieht, was ich nicht meinte. Deine Argumentation geht nur auf, wenn ich gewollt hätte, dass in
List<T>
der Speicher neu angelegt wird, was aber eben nicht der Fall ist. Ich habe daher überhaupt nichts zurechtgebogen, ich verstehe absolut, was du meinst. Aber du scheinst wohl immer noch nicht zu verstehen, was ich meine.Grüssli
-
Dravere schrieb:
Kommt darauf an, was man alles zu Funktionalität von Array.Resize nimmt oder als Implementationsdetail sieht.
Ich denke da liegt das Problem und warum wir ein wenig aneinander vorbeireden.
Ich habe versucht gegen ein List.Resize zu argumentieren und es dabei direkt mit dem Array.Resize verglichen, so wie es arbeitet. Du dagegen gehst von einer Annahme aus, die nicht stimmt. Und zwar
Falls es grösser ist, dann sind die neuen Elemente mit einem Defaultwert oder
null
initialisiert.Der Typ des Arrays und damit die Art was für Elemente drin sind ist vollkommen egal, da weder irgend ein Defaultwert noch null für die zugekommenen Elemente verwendet wird. Es wird nur ein neuer Speicherbereich angefordert in der neuen Größe und die alten Elemente umkopiert, mehr passiert nicht. Sämtlicher neuer Speicher ist einfach uninitialisiert. Das ist nen kleiner aber feiner Unterschied.
Und da tritt jetzt auch der Konflikt mit der List auf. So ein Verhalten macht bei einer List gar keinen Sinn, da es eine Liste ist bei der bekannt ist wieviel Elemente vorhanden sind und nach außen hin es niemals Elemente gibt die uninitialisiert sind, ganz im Gegensatz zu einem Array.
Was du im Endeffekt machen wolltest war schon klar nachdem du sagtest dass du im Prinzip einfach nur Elemente hinzufügen willst um Count zu ändern. Was ich darauf hin versucht hab ist, nur klarzustellen das es nicht das gleiche ist wie Array.Resize sondern technisch was ganz anderes passiert und das sowas nichts in einer List zu suchen hat, was ja ursprünglich mal die Eingangsfrage war. Array.Length, welches durch das Resize geändert wird, entspricht dem list.Capacity, nicht dem List.Count. Da hätt diese Fehlannahme vielleicht schon auffallen können.
Abgesehen von der Thematik hast du trotzdem das Argument verbogen. Du hast mein Argument mit Ursache -> Wirkung als Wirkung -> Ursache dargestellt. Das hab ich im letzten Absatz des letzten Posts ja versucht zu erklären. Vielleicht trägt der Absatz mit dem Wissen, das wir unterschiedliche Grundannahmen hatten, ja mehr dazu bei, dieses Verdrehen zu verstehen was dort passiert ist.
Und zum Vergleich mit dem std:vector:resize: Dieses Verhalten kann man in .Net gar nicht nachbilden. In der STL gibts zwei Überladungen. Einmal mit einem Value, wo immer Kopien als neues Element angefügt werden sollen bis die neue Größe erreicht wird, und einmal ohne Value wo einfach das letzte Element immer kopiert wird. Und da ist der Knackpunkt. Es gibt in .Net keine allgemeingültige Funktion mit der beliebige Objekte kopiert werden können. Bei ValueTypes ist es noch leicht möglich, aber bei ReferenceTypes ist es unmöglich. Deshalb kann es so ein Resize in .Net nicht geben. Das vielleicht noch mit ein Grund warum es sowas in der .Net Standardbibliothek nicht gibt, selbst wenn man sowas, warum auch immer, doch vorgehabt hätte für die List.
-
Ich habe gesagt dass ein Resize bei einer List, wenn es so wie bei einem Array durchgeführt wird, in die Wachstumsstategie der List eingreift und man damit praktisch den internen Speicher der List selber verwaltet.
Nur wenn Resize(N) garantiert, dass danach Capacity == N gilt.
Wenn Resize(N) nur garantiert, dass danach Capacity >= N gilt, dann darf die List ja weiterhin tun und walten wie sie mag...
-
Zwergli schrieb:
Und zum Vergleich mit dem std:vector:resize: Dieses Verhalten kann man in .Net gar nicht nachbilden. In der STL gibts zwei Überladungen. Einmal mit einem Value, wo immer Kopien als neues Element angefügt werden sollen bis die neue Größe erreicht wird, und einmal ohne Value wo einfach das letzte Element immer kopiert wird.
NEIN!
Die Variante mit nur einem Parameter (std::vector<T>::resize(size_type)) initialisiert die neuen Elemente mit dem Default-Konstructor (genauer: sie werden "default initialized").
Wo nimmst du nur solchen Unsinn her? Und wieso postest du ihn dann auch noch?
-
Zwergli schrieb:
Der Typ des Arrays und damit die Art was für Elemente drin sind ist vollkommen egal, da weder irgend ein Defaultwert noch null für die zugekommenen Elemente verwendet wird. Es wird nur ein neuer Speicherbereich angefordert in der neuen Größe und die alten Elemente umkopiert, mehr passiert nicht. Sämtlicher neuer Speicher ist einfach uninitialisiert. Das ist nen kleiner aber feiner Unterschied.
Seit wann gibt es in C# uninitialisierter Speicher? Wir sind hier doch nicht in C oder C++. Also das musst du mir zuerst einmal mit entsprechender Quelle beweisen. Wenn ein neues Array angelegt wird, sind die Element schliesslich auch mit einem entsprechenden Defaultwert belegt.
Quelle: http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx
The default value of numeric array elements are set to zero, and reference elements are set to null.
Zwergli schrieb:
Was du im Endeffekt machen wolltest war schon klar nachdem du sagtest dass du im Prinzip einfach nur Elemente hinzufügen willst um Count zu ändern. Was ich darauf hin versucht hab ist, nur klarzustellen das es nicht das gleiche ist wie Array.Resize sondern technisch was ganz anderes passiert und das sowas nichts in einer List zu suchen hat, ...
Sorry, aber mit dieser Aussage glaube ich nicht, dass du verstanden hast, was ich wollte oder dann fehlt dir hier Wissen über die Möglichkeiten einer
List<T>
. Ich sehe jedenfalls keine technischen Einschränkungen, es ist absolut möglich und beeinflusst auch die Speicherverwaltung vonList<T>
in keiner Weise. Deine Argumentation ist schlicht und einfach falsch.Du gehst ja auch davon aus, dass beim Verändern der Array Grösse neuer Speicher auf dem Stack angelegt wird, was auch komplett falsch ist. Der GC ist für die Allokierung des Speichers verantwortlich, auf dem Stack wird da nichts gemacht.
Zwergli schrieb:
...was ja ursprünglich mal die Eingangsfrage war.
Ich habe nie nach sowas gefragt. Ich weiss sehr genau wie
List<T>
undArray.Resize
intern funktionieren.Zwergli schrieb:
Array.Length, welches durch das Resize geändert wird, entspricht dem list.Capacity, nicht dem List.Count. Da hätt diese Fehlannahme vielleicht schon auffallen können.
Dass das interne Array dem entspricht ist mir absolut bewusst. Ich habe nie etwas Gegenteiliges behauptet.
Zwergli schrieb:
Abgesehen von der Thematik hast du trotzdem das Argument verbogen. Du hast mein Argument mit Ursache -> Wirkung als Wirkung -> Ursache dargestellt. Das hab ich im letzten Absatz des letzten Posts ja versucht zu erklären. Vielleicht trägt der Absatz mit dem Wissen, das wir unterschiedliche Grundannahmen hatten, ja mehr dazu bei, dieses Verdrehen zu verstehen was dort passiert ist.
Nein, ich habe dagegen immer wie mehr das Gefühl, dass dir an einigen Stellen Wissen fehlt oder falsches Wissen vorhanden ist und es deshalb zu diesen Missverständnissen kam.
Zwergli schrieb:
Und zum Vergleich mit dem std:vector:resize: Dieses Verhalten kann man in .Net gar nicht nachbilden. In der STL gibts zwei Überladungen. Einmal mit einem Value, wo immer Kopien als neues Element angefügt werden sollen bis die neue Größe erreicht wird ...
Nein, es wird im allgemeinen nicht einfach nur immer Kopien hintenangefügt. Meistens wird zuerst geprüft, ob es genug Speicher hat, wenn dies nicht der Fall ist, wird zuerst der interne Speicher vergrössert. Danach wird einfach jedes neue Element per Placement New CopyInitialised. Dann wird noch die Grösse angepasst.
Sowas könnte man auch in einer
List<T>
umsetzen, ohne Probleme. Gut, vielleicht hätte man gewisse Probleme beim Initialisieren per Kopie von Referenztypen. Obwohl es hier zwarICloneable
gäbe. Aber ich hätte mich ja auch sehr damit zufrieden gegeben, wenn danach einfach Standardwerte drin sind und dies geht nun wirklich ohne Probleme.Zwergli schrieb:
..., und einmal ohne Value wo einfach das letzte Element immer kopiert wird.
Zeugt von absoluter Unwissenheit und auch davon, dass du den Link immer noch nicht gelesen hast. Es gibt genau eine Version. Diese Version hast für den zweiten Parameter einfach einen vorgegebenen Wert, welcher über den Standardkonstruktor initialisiert und danach reinkopiert wird. Es wäre allerdings theoretisch auch absolut kein Problem, für alle neuen Elemente den Standardkonstruktor aufzurufen. Jedenfalls haben dadurch dann alle neuen Elemente einen Standardwert, wenn man kein eigenes Initialisierungsobjekt angibt.
Zwergli schrieb:
Und da ist der Knackpunkt. Es gibt in .Net keine allgemeingültige Funktion mit der beliebige Objekte kopiert werden können.
Da eben auch der Standardwert genommen werden kann, spielt dies keine Rolle. Zudem gäbe es, wie schon gesagt,
ICloneable
für Referenztypen. Wertetypen sind von Haus aus kopierbar.Grüssli
-
Lest euch alles von Anfang an durch, absolut lesenswert!!! lolololol
-
C# scheint irgendwie deutlich mehr Aggressionen hervorzurufen, als C++ ...
ich hätte den Thread auch nie gefunden, wenn ich nicht gerade zufällig auch mit C# arbeiten müsste.Da lob ich mir doch den Frieden in der C++-Abteilung