List<T> - Resize?
-
Hallo zusammen,
Einfache Frage:
Gibt es beiList<T>
keineResize
Funktionalität? Was gibt es da für alternative Möglichkeiten?Grüssli
-
MSDN is your friend
The capacity of a List<(Of <(T>)>) is the number of elements that the List<(Of <(T>)>) can hold. As elements are added to a List<(Of <(T>)>), the capacity is automatically increased as required by reallocating the internal array.
If the size of the collection can be estimated, specifying the initial capacity eliminates the need to perform a number of resizing operations while adding elements to the List<(Of <(T>)>).
The capacity can be decreased by calling the TrimExcess method or by setting the Capacity property explicitly. Decreasing the capacity reallocates memory and copies all the elements in the List<(Of <(T>)>).
-
Du verstehst mich falsch, ich meine eher sowas in der Art von Array.Resize. Ich möchte also die
List<T>
von 5 Elementen aufx
Elemente bringen, fallsx
grösser ist, solly
als Standardelement verwendet werden.Ähnlich wie zum Beispiel ein std::vector::resize aus C++.
Grüssli
-
Dravere schrieb:
Du verstehst mich falsch,
er versteht Dich richtig ... nur - entweder kannst Du keine Englisch oder Du willst Dich nicht mit der MSDN auseinander setzen ... im letzteren Fall ... List kennt die Resize Methode nicht - musst Du Dir dann wohl selber was basteln
ich quote Dir nochmal den relevanten Teil aus seinem Posting
[...] the capacity is automatically increased as required by reallocating the internal array [...]
hand, mogel
-
Sagt mal, wisst ihr eigentlich was die
Capacity
ist? Ich will nichtCapacity
verändern, sondernCount
. Ich will die Anzahl der Elemente verändern und nicht die grösse der Kapazität.Grundsätzlich möchte ich sowas haben:
public class MyClass { // Attributes // private List<Foo> m_foos; // ... // Constructors // public Myclass() { m_foos = new List<Foo>(); } // ... // Methods // public void changeSize(int newSize) { // Hier möchte ich eine einfache Möglichkeit haben. // Halt sowas wie Array.Resize while(m_foos.Count > newSize) { m_payments.RemoveAt(m_payments.Count - 1); } for(int i = m_foos.Count; i < newSize; ++i) { m_foos.Add(new Foo()); } } };
Ganz übertrieben einfach dargestellt, damit nun hoffentlich der allerletzte es verstehen wird ...
Grüssli
-
na da hast du dir doch direkt schon wunderbar ein resize gebastelt - ist doch genau das was du auch moechtest {o;
Capacity ist glaub ich die angabe wieviel das objekt maximal behalten kannbastel dir doch einfach ne extension method
public static class Addon { public static void Resize<T>(this List<T> list, int newSize) { while (list.Count > newSize) list.RemoveAt(list.Count - 1); for (int i = list.Count; i < newSize; ++i) list.Add(Activator.CreateInstance<T>()); } }
spaetere benutzung ist dann einfach:
List<int> list = new List<int>(); list.Resize(15);
-
Mr Evil schrieb:
bastel dir doch einfach ne extension method
Bereits schon getan, allerdings wundert es mich eben, dass
List<T>
sowas nicht bereits selber aufweist. Ich sehe nicht mehr so gut, habe ende dieses Monats einen Termin beim Augenarzt, vielleicht überseh ich ja wasOder gibt es irgendwo eine Klasse mit statischen Funktionen, wo dies bereits vorhanden ist? Oder andere Möglichkeiten? Vielleicht ist es in einer anderen Funktionalität mitintegriert?
Grüssli
-
Vielleicht braucht man sowas normalerweise auch einfach nicht.
-
Wieso sollte List<T> sowas aufweisen? Deine Variante funktioniert doch nur wenn T nen Standardkonstruktor hat, was net der Fall sein muss. Wie soll man von Klassen neue Objekte erstellen wenn die keinen Standardkonstruktor haben und man net weiß was die benutzerdefinierten für Werte erwarten? Array.Resize erstellt auch keine neune Objekte der Klassen, von daher unterscheidet sich auch die Funktionalität von dem Array.Resize und dem hier vorgestellten Resize für List<T>.
-
Zwergli schrieb:
Wieso sollte List<T> sowas aufweisen?
Um so ein Vorgehen zu vereinfachen? Um die entsprechende Funktionalität anzubieten? Ein optimales Verfahren bereits einbauen? Was für eine Frage ist denn das?
Zwergli schrieb:
Deine Variante funktioniert doch nur wenn T nen Standardkonstruktor hat, was net der Fall sein muss. Wie soll man von Klassen neue Objekte erstellen wenn die keinen Standardkonstruktor haben und man net weiß was die benutzerdefinierten für Werte erwarten?
Ein wenig Fantasie anwenden:
using System; using System.Collections.Generic; namespace SharpTest { public class MainClass { // Static functions // static public void Main(string[] args) { List<Foo> mylist = new List<Foo>(); mylist.Add(new Foo(0, "hello")); mylist.Resize(10, 1, "test"); foreach(Foo foo in mylist) { Console.WriteLine("{0} - {1}", foo.Number, foo.Name); } Console.WriteLine("-------------------------"); List<int> myints = new List<int>(); myints.Resize(10); foreach(int i in myints) { Console.WriteLine(i); } Console.ReadKey(); } } static class ListMethodExtension { public static void Resize<T>(this List<T> list, int newSize, params object[] constructorParams) { while(list.Count > newSize) { list.RemoveAt(list.Count - 1); } for(int i = list.Count;i < newSize;++i) { T obj = (T)Activator.CreateInstance(typeof(T), constructorParams); list.Add(obj); } } } class Foo { public int Number { get; set; } public string Name { get; set; } public Foo(int number, string name) { this.Number = number; this.Name = name; } } }
Ich bin nicht der vollprofi was C# angeht, aber es scheint möglich zu sein. Wieso also nicht?
Zwergli schrieb:
Array.Resize erstellt auch keine neune Objekte der Klassen, von daher unterscheidet sich auch die Funktionalität von dem Array.Resize und dem hier vorgestellten Resize für List<T>.
Ich hätte nicht einmal etwas dagegen, wenn es einfach beim Vergrössern die neuen Element mit einem Standardwert oder
null
initialisiert. Also genau wie esArray.Resize
macht. Aber nicht einmal sowas gibt es.Grüssli
-
Irgendwie beginnen mir die Threads, wo jemand rumsudert dass es irgendwas nicht gibt, schön langsam auf den Keks zu gehen.
-
hustbaer schrieb:
Irgendwie beginnen mir die Threads, wo jemand rumsudert dass es irgendwas nicht gibt, schön langsam auf den Keks zu gehen.
Wieso rumsudern? Ich meckere nicht über C# oder .Net, ich habe nur gefragt, ob es eine entsprechende Möglichkeit gibt. Und dann wurde ich deswegen zum Teil geradezu angefahren. Ich kritisiere C# oder .Net in keinster Weise, dass es sowas nicht anbietet!
Zuerst wirft man mir vor, dass ich die MSDN nicht lesen kann. Dann wirft man mir vor, dass ich Beiträge nicht richtig lese.
Dann kommt Mr.Evil, welcher mir einen hilfreichen Tipp gibt, nach welchem ich zwar nicht unbedingt gefragt habe, aber dafür trotzdem danke.
Danach frage ich nochmals nach, ob es wirklich nicht anders geht. Dann kommt der erste Troll, mit einer Aussage die überhaupt nichts bringt und der zweite, welcher wieder nicht auf meine Frage eingeht, sondern es geradezu für wahnsinnig haltet, dass man sowas überhaupt fragen kann. Mein BEISPIEL kritisiert, obwohl es nur ein Beispiel zur Verdeutlichung ist und dann erst noch mit einer Kritik die nicht haltbar ist.
Und am Ende werde ich dann noch kritisiert, dass ich rumsudere?Zum Geier nocheinmal, ich fange gleich an rumzusudern ... lol
Ich habe eine wahnsinnig einfache Frage gestellt, bekomme keine Antwort darauf und werde nur angefahren. Unglaublich! Darf man nicht mehr Fragen stellen? Oder habe ich gegen irgendein heiliges Gesetz verstossen? Einen heiligen Friedhof betreten?
Grüssli
-
Ich hätte nicht einmal etwas dagegen, wenn es einfach beim Vergrössern die neuen Element mit einem Standardwert oder null initialisiert. Also genau wie es Array.Resize macht. Aber nicht einmal sowas gibt es.
Eine Liste verwendet man wenn es keine Rolle spielt wie viele Elemente exakt verwendet werden (z.B. weil man vorher nicht weiß wie viel Elemente es geben wird.) Es schaut nach einem Fehler im Design aus, nicht nach einer fehlenden Funktionalität. Wenn Du ein Array brauchst -> verwende auch eines.
-
Knuddlbaer schrieb:
Eine Liste verwendet man wenn es keine Rolle spielt wie viele Elemente exakt verwendet werden (z.B. weil man vorher nicht weiß wie viel Elemente es geben wird.) Es schaut nach einem Fehler im Design aus, nicht nach einer fehlenden Funktionalität. Wenn Du ein Array brauchst -> verwende auch eines.
Verstehe ich nicht, wieso dies ein Fehler im Design sein soll. Ich möchte hier nur nochmals klarstellen, dass es nicht um die Capacity geht. Ich möchte nur die Möglichkeit haben mit einem Funktionsaufruf automatisch eine neue Menge an Elementen zu definieren. Die Anzahl Elemente sind im voraus nicht bekannt und die Grösse kann sich je nach dem verändern. Ich möchte allerdings auch jederzeit einzelne Elemente dazufügen oder entfernen können und dafür nicht jedesmal nur für ein einzelnes Element
Array.Resize
aufrufen müssen.List<T>
wäre da deutlich praktischer, da es intern mit einer Capacity funktioniert, daher auch durchaus performanter sein kann.Es leuchtet mir wirklich nicht ein, wieso dies ein Designfehler sein sollte. Grundsätzlich gibt es zudem schon
AddRange
undRemoveRange
. Es musste eine Funktion nur diese beiden Funktion verbinden, wenn vergrösster wird, wirdAddRange
aufgerufen, bei einer Verkleinerung dagegenRemoveRange
oder irgendwas in der Art.
Und alles was ich mir zu fragen erlaube ist, ob es sowas nicht bereits schon hat. Vielleicht irgendwo in einer Utility Klasse oder sowas ähnliches.Grüssli
-
Dravere schrieb:
(...)
Ja du hast wohl Recht.
In letzter Zeit häufen sich Threads wo irgendwer fragt wie man XYZ macht, wobei XYZ dann etwas ist was einfach nicht geht. Und dann fängt das Gesudere an.In deinem Fall war die Frage durchaus OK und die Antworten... fragwürdig. Sorry, hätte den Thread etwas aufmerksamer lesen sollen.
-
Dravere schrieb:
Was für eine Frage ist denn das?
Ne ernstgemeinte, auch wenn du sie als Trollversuch hinstellen möchtest.
Was möchtest du erreichen: Die Anzahl der Objekte in der Liste ändern mit einer Art Resize. Da sind wir uns einig oder?
Gucken wir mal was Array.Resize macht, welches du ja zum Vergleich hergenommen hast. Ein Array hat eine bestimmte Größe (durch das Length Property veröffentlich) welches angibt wieviel Elemente das Array umfassen kann. Wieviele Elemente im Array sind, wird durch kein Property veröffentlicht. Ein Resize ist notwendig, da die Arraygröße fix ist und bei einer gewünschten Größenänderung erst neuer Speicher aufm Stack angefordert werden muss und die Elemente des Array umkopiert werden müssen. Im Prinzip ist Array.Resize nur aus geschichtlichen Gründen drin, die Funktion an sich ist vollkommen überflüssig.
Nun zur List<T>: Ne Liste von Objekten mit variabler Länge. Das die intern auch nur ein Array wrappt ist für die Betrachtung jetzt mal egal. Aber wir haben zwei Properties: Count und Capacity. Count gibt an wieviel Objekte hinzugefügt wurden. Sprich, im Gegensatz zum Array gibt es hier ein Property welches die Anzahl der Elemente festhält. Capacity gibt nun an wieviel Elemente durch die interne Datenstruktur gespeichert werden können. Die Liste wächst dabei automatisch, so dass Capacity auch wächst. Wenn man vergleicht sieht man, dass Array.Length dem List<T>.Capacity entspricht, nicht dem List<T>.Count!
Das ist ein wichtiger Punkt, weil daraus direkt folgt das ein Resize für die List vollkommen unnötig ist, da die Liste ja selber wächst. Und für den Schrumpffall gibts ja TrimExcess. Manuell in der, ich nenns mal Wachstumsstrategie, der Liste rumzupfuschen, ist total unnötig, dann bräuchte man keine Liste.
Ich hätte nicht einmal etwas dagegen, wenn es einfach beim Vergrössern die neuen Element mit einem Standardwert oder null initialisiert. Also genau wie es
Array.Resize
macht. Aber nicht einmal sowas gibt es.Ich hoffe diese Aussage habe ich durch meine Argumentation oben geklärt. Was Array.Resize macht, und was du machen willst, sind zwar vollkommen unterschiedliche Paar Schuhe.
Zwergli schrieb:
Ein wenig Fantasie anwenden:
... Wieso also nicht?Nettes Stückchen Code, funktioniert natürlich, ist designtechnisch aber vollkommer Schwachsinn. Als Extension Method ist das noch geradeso erträglich weil das einfach benutzerdefinierter Code ist den der Entwickler sich gewünscht hat.
Aber so eine Funktion hat in der List Klasse nie und nimmer was zu suchen. Alleine das Activator.CreateInstance kann 10 verschiedene Exceptions werfen, man selber kann im Konstruktor der Klasse die instanziert werden soll, auch Exceptions werfen, und was soll die List dann machen? Exception schlucken und Count nicht erhöhen? Exceptions nach außen geben? Auch funktioniert Activator.CreateInstance für bestimmte Typen, nur mit bestimmten Permissons die man unter Umständen dem Code nicht geben möchte. Und schon hat man rechtetechnisch nen riesen Problem, und das bei einer Klasse die doch nur Objekte in einer Liste verwalten soll und durch solchen Code bei weitem nicht so allgemein eingesetzt werden kann wie sie soll.
Framework Klassen müssen allgemein gehalten sein und genau ihren Zweck erfüllen. Sicherlich wünscht man sich öfter mal bei nem bestimmten Problem, das Funktion xyz in Frameworkklasse abc schön wäre. Geht aber nicht.
Ich versteh dein Problem an sich auch net. Ne Schleife die dir die fehlenden Objekte in ne Liste packt sind 3 Zeilen Code, wieso willst du diesen viel zu umständlichen Weg gehen?
-
Zwergli schrieb:
Ich hoffe diese Aussage habe ich durch meine Argumentation oben geklärt. Was Array.Resize macht, und was du machen willst, sind zwar vollkommen unterschiedliche Paar Schuhe.
Du verstehst immer noch nicht was ich will. Das ist unglaublich ...
Lies das folgende im Link! Den habe ich auch schon einmal angegeben. Aber den hast du wohl lieber überlesen.
http://www.cplusplus.com/reference/stl/vector/resize/Ich will genau das Verhalten von
Array.Resize
fürList<T>
, einfach alsList<T>.Resize
, welches nicht dieCapacity
verändert, sondern die Anzahl Elemente, alsoList<T>.Count
. Mir ist scheiss egal wieList<T>
intern den Speicher verwaltet, den will ich nicht antasten, dass habe ich jetzt wohl echt oft genug gesagt.Zwergli schrieb:
Ich versteh dein Problem an sich auch net. Ne Schleife die dir die fehlenden Objekte in ne Liste packt sind 3 Zeilen Code, wieso willst du diesen viel zu umständlichen Weg gehen?
Ich habe gefragt, ob man diese paar Zeilen mit einer einzigen Methode vereinfachen kann, welche ich womöglich nicht gefunden habe. Das schreibe ich nun auch zu X-ten Mal. Mehr will ich nicht! Grundsätzlich hätte am Anfang als Antwort nur ein JA oder NEIN gereicht. Aber damit überfordere ich euch anscheinend
Grüssli
-
- Man will auch nicht jede denkbare Methode in ein Interface packen
- Eine Liste ist semantisch etwas anderes als ein Vektor. Das Interface spiegelt die Semantik wieder.
- Die Anwendungsfälle für das Resize, wie es in vector implementiert ist, dürften in einer Liste im allgemeinen selten sein.
Fazit: Wenn Du einen Vektor haben willst, dann bau Dir einen Vektor.
-
hajb schrieb:
Man will auch nicht jede denkbare Methode in ein Interface packen
Darum geht es mir nicht, zum x+1'ten Mal. Ich habe sowas nie gefordert, nur nachgefragt.
hajb schrieb:
Eine Liste ist semantisch etwas anderes als ein Vektor. Das Interface spiegelt die Semantik wieder.
Du weisst aber hoffentlich, was ein STL Vektor ist? Das ist kein Graphikvektor oder sowas, sondern hat die genau gleiche Funktionalität, wie eine
List<T>
.hajb schrieb:
Die Anwendungsfälle für das Resize, wie es in vector implementiert ist, dürften in einer Liste im allgemeinen selten sein.
Begründung? Oder muss man heute seine Argumente nur noch hinwerfen und dann gelten sie als korrekt?
hajb schrieb:
Fazit: Wenn Du einen Vektor haben willst, dann bau Dir einen Vektor.
Will ich nicht! Lesen hier eigentlich alle nur, was sie lesen wollen?
Grüssli
-
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