List<T> - Resize?



  • 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>.


  • Administrator

    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 es Array.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.


  • Administrator

    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.


  • Administrator

    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 und RemoveRange . Es musste eine Funktion nur diese beiden Funktion verbinden, wenn vergrösster wird, wird AddRange aufgerufen, bei einer Verkleinerung dagegen RemoveRange 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?


  • Administrator

    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ür List<T> , einfach als List<T>.Resize , welches nicht die Capacity verändert, sondern die Anzahl Elemente, also List<T>.Count . Mir ist scheiss egal wie List<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.


  • Administrator

    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".


  • Administrator

    @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 von List<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.


  • Administrator

    @Zwergli,
    Kommt darauf an, was man alles zu Funktionalität von Array.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 oder null 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 mehrmals Add , bzw. Remove aufruft. Auch std::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?


  • Administrator

    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 von List<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> und Array.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 zwar ICloneable 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


Anmelden zum Antworten