PictureBoxen zur Laufzeit erstellen



  • Es läuft nun - mit dem Code (fast) wie ich gehabt habe. Das Problem war ein ganz anderes; und zwar

    for(int i = 0; i < 10;i++)
    

    anstatt

    for(int i = 0; i ==10;i++)
    

    sowie

    FileInfo f=myfileinfos[index].ToString();
    PictureBox.LoadAsync(f.FullName
    

    anstatt

    PictureBox.LoadAsync(myfileinfos[index].ToString()); (oder Image.FromFile)
    

    da der Pfad nicht übergeben wurde.
    Nun aber habe ich ein anderes Problem: DIe Pictureboxen werden in der Mitte des Fensters angeordnet, d.h. wenn man nicht hinunterscrollt sieht man nichts. WIe /was muss ich da dem FlowLayoutPanel zuweisen damit es das nicht tut? FlowDirection=TopDown geht auch nicht, das beginnt zwar oben aber nicht am linken Rand sondern hier wiederum in der Mitte (muss man also nach rechts scrollen).

    Vielen Dank 🙂



  • Ein wenig MSDN ist auch für Dich übrig...

    Geht Dein Panel überhaupt über die gesamte Fläche oder klebt die einfach nur mittendrinn ?



  • Knuddlbaer schrieb:

    ... zum anderen kannst Du Kopien von der Referenz so viele Kopien anliegen so viel du willst, die Operation wird am Objekt ausgeführt auf das die Referenz zeigt. Selbst wenn der Enumerator Kopien erzeugt wären es nur Kopien der Referenz.

    das nahm ich zuerst auch an, nur als ich foreach mal intensiever in mein code eingebaut hatte - hatte es mal nicht funktiert, die zuweisung ging floeten - seit dem vermeide ich ein foreach wenn ich die elemente irgendwie veraendern muss - da es meiner erfahrung nach auch zu blanken kopien kommen kann statt einer kopie einer referenz

    ich schau mal ob ich es noch find, aber denk nicht da ich es gleich als for umgebaut hatte als es nicht funktionierte

    //Dazuedit, grad probiert, nichtmal der compiler laessts durch:

    List<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    numbers.Add(3);
    numbers.Add(4);
    numbers.Add(5);
    
    foreach (int number in numbers)
        number += 10;
    
    foreach (int number in numbers)
        Console.WriteLine(number);
    

    VS08 schrieb:

    Cannot assign to 'number' because it is a 'foreach iteration Variable'

    mit diesem das selbe:

    struct Number
    {
        public int Value;
    }
    
    static void Main(string[] args)
    {
        List<Number> numbers = new List<Number>();
        numbers.Add(new Number());
        numbers.Add(new Number());
        numbers.Add(new Number());
        numbers.Add(new Number());
        numbers.Add(new Number());
    
        foreach (Number number in numbers)
            number.Value += 10;
    
        foreach (Number number in numbers)
            Console.WriteLine(number.Value);
    

    fuer mich ist das ein inkosistentes verhalten, daher vermeide ich es objekte zu veraendern welche aus einer foreach kommen

    ich hatte wie gesagt schon den fall das ic variablen veraendert hatten, und im laufenden programm dann die zuweisung nicht beachtet wurde, bis ich es als for umgebaut hab



  • int ist ja auch ein struct. Damit geht das natürlich nicht.
    Mit Klassen funktioniert das aber.



  • was heisst "natuerlich" - wo ist die logik dahinter das es mit class geht aber struct nicht ???

    http://msdn.microsoft.com/de-de/library/cc433531(VS.71).aspx

    MSDN schrieb:

    ...muss einen der folgenden Typen darstellen: interface, class oder struct....

    laut MSDN solls auch mit struct gehen



  • Weil structs Wertetypen sind und in der foreach-Schleife einer Variablen dann halt
    ein Wert und keine Referenz zugewiesen wird.



  • genau - darum sagte ich ja

    da es meiner erfahrung nach auch zu blanken kopien kommen kann statt einer kopie einer referenz
    

    ich verlass mich da nicht drauf das ich in foreach werte direkt aendern kann welche auch wirklich zugewiesen werden

    btw. falls sich wer wundert, ich bastel derzeit an mein greasemonkey script rum und deswegen ist er derzeit nicht aktiv



  • Mmh, okay, wobei man das Problem aber nicht nur bei foreach hat.
    Das geht doch eher um Structs und Klassen und das man die zugegeben schlecht unterscheiden kann.



  • stimmt auch wieder - bei funktionsaufrufen ist es das selbe - da werden nur klassen als referenzen uebergeben
    structs nicht /=

    "string" wird auch nicht als referenz uebergeben sondern als kopie, sofern es nicht bestandteil einer klasse ist

    class NumberClass
    {
    	public NumberClass(int number)
    	{
    		Value = number;
    	}
    	public int Value { get; set; }
    }
    
    struct NumberStruct
    {
    	public int Value;
    }
    
    class TextClass
    {
    	public TextClass(string text)
    	{
    		Value = text;
    	}
    	public string Value { get; set; }
    }
    
    //-------------------------------------------------------
    static void Increaser(NumberClass p)
    {
    	p.Value += 10;
    }
    static void Increaser(NumberStruct p)
    {
    	p.Value += 10;
    }
    static void Increaser(int p)
    {
    	p += 10;
    }
    static void Changer(string p)
    {
    	p = "11";
    }
    static void Changer(TextClass p)
    {
    	p.Value = "11";
    }
    //-------------------------------------------------------
    
    static void Main(string[] args)
    {
    	NumberClass numberClass = new NumberClass(1);
    	NumberStruct numberStruct = new NumberStruct();
    	numberStruct.Value = 1;
    	int number = 1;
    	string numberText = "1";
    	TextClass textClass = new TextClass("1");
    	Console.WriteLine("Before numberclass: " + numberClass.Value);
    	Console.WriteLine("Before struct: " + numberStruct.Value);
    	Console.WriteLine("Before int: " + number);
    	Console.WriteLine("Before string: " + numberText);
    	Console.WriteLine("Before textclass: " + textClass.Value);
    
    	Increaser(numberClass);
    	Increaser(numberStruct);
    	Increaser(number);
    	Changer(numberText);
    	Changer(textClass);
    
    	Console.WriteLine("After numberclass: " + numberClass.Value);
    	Console.WriteLine("After struct: " + numberStruct.Value);
    	Console.WriteLine("After int: " + number);
    	Console.WriteLine("After string: " + numberText);
    	Console.WriteLine("After textclass: " + textClass.Value);
    }
    

    Console schrieb:

    Before numberclass: 1
    Before struct: 1
    Before int: 1
    Before string: 1
    Before textclass: 1
    After numberclass: 11
    After struct: 1
    After int: 1
    After string: 1
    After textclass: 11

    und das obwohl string, int usw auch klassen sind
    ich find das verwirrend



  • Den foreach loop kannst Du Dir grob so vorstellen:

    foreach(T x in y) { ...}
    
    for(int counter = 0; counter < y.Length; counter++)
    {
       readonly T tmp = y[counter];
       ....
    }
    

    Bei Enumeratoren schauts ein wenig anders aus. Vllt. hilft das ein wenig als Brücke zu den foreach Konstrukten.

    Ansonsten lies mal die Sätze die drüber stehen.

    Um eine Auflistung durchlaufen zu können, muss [...] Der Auflistungstyp einen der folgenden Typen darstellen: interface, class oder struct [...]

    "string" wird auch nicht als referenz uebergeben sondern als kopie, sofern es nicht bestandteil einer klasse ist

    Wie kommst Du nun drauf ?

    ublic sealed class String
    

    spricht doch sehr dafür das auch ein String als Referenz übergeben wird.



  • Knuddlbaer schrieb:

    "string" wird auch nicht als referenz uebergeben sondern als kopie, sofern es nicht bestandteil einer klasse ist

    Wie kommst Du nun drauf ?

    ublic sealed class String
    

    spricht doch sehr dafür das auch ein String als Referenz übergeben wird.

    weil ich es getestet hab, schau mal den code oben an, und das ergebnis, ich kuerz es mal der uebersicht zuliebe zusammen:

    class TextClass
    {
        public TextClass(string text)
        {
            Value = text;
        }
        public string Value { get; set; }
    }
    
    //-------------------------------------------------------
    static void Changer(string p)
    {
        p = "11";
    }
    static void Changer(TextClass p)
    {
        p.Value = "11";
    }
    //-------------------------------------------------------
    
    static void Main(string[] args)
    {
        string numberText = "1";
        TextClass textClass = new TextClass("1");
        Console.WriteLine("Before string: " + numberText);
        Console.WriteLine("Before textclass: " + textClass.Value);
    
        Changer(numberText);
        Changer(textClass);
    
        Console.WriteLine("After string: " + numberText);
        Console.WriteLine("After textclass: " + textClass.Value);
    }
    

    Console schrieb:

    Before string: 1
    Before textclass: 1
    After string: 1
    After textclass: 11

    wie man sieht ist der string nur veraendert wurden wenn er in einer klasse gekapselt ist
    und wenn man sich das gesamte beispiel in mein vorherigen posting an schaut, sieht man das es nur als referenz uebergeben wird wenn es eine eigene klasse ist
    int, long, string usw werden als kopie uebergeben - obwohl es auch nur klassen sind /=



  • Tu Dir doch einfach mal selbst den gefallen und schau Dir die String Klasse mal in der Dokumentation an. Man kann mit etwas Intuition schon gut raten und eine Richtung für die Dokumentation haben um weitere Informationen zu suchen.

    Die von Dir genannten Beispiele und diese Diskussion wären für mich der Anlass noch mal in die Dokumentation zu schauen. Aber selbst ohne dem Wissen, das System.String nicht änderbar ist und jede Änderung eine neue Instanz von System.String erzeugt ist die Erkenntnis die Du aus Deinem Beispielcode zeigst noch ausbaufähig.

    namespace ConsoleApplication2
    {
    
        class Beispielklasse
        {
            public override string ToString()
            {
                return name;
            }
    
            string name;
            /// <summary>
            /// Initializes a new instance of the Beispielklasse class.
            /// </summary>
            /// <param name="name"></param>
            public Beispielklasse(string name)
            {
                this.name = name;
            }
    
            public static void Changer(Beispielklasse var)
            {
                var = new Beispielklasse("Changer(Beispielklasse var)");
            }
            public static void Changer(ref Beispielklasse var) 
            {
                var = new Beispielklasse("Changer(ref Beispielklasse var)");
            }
    
        }
        class Program
        {
            static void Main(string[] args)
            {
                Beispielklasse bsp = new Beispielklasse("Main");
                Console.WriteLine(bsp);
                Beispielklasse.Changer(bsp);
                Console.WriteLine(bsp);
                Beispielklasse.Changer(ref bsp);
                Console.WriteLine(bsp);
            }
        }
    }
    
    Beispielklasse.Changer(bsp);
    

    Hier wird eine Kopie der Referenz erzeugt. Die Kopie der Referenz wird auf einen neuen Wert gesetzt.

    class Program
        {
            public static void Changer(string var)
            {
                var = "changer(string)";
            }
            public static void Changer(ref string var)
            {
                var = "changer(ref string)";
            }
    
            static void Main(string[] args)
            {
                string test = "Main";
                Console.WriteLine(test);
                Program.Changer(test);
                Console.WriteLine(test);
                Program.Changer(ref test);
                Console.WriteLine(test);
            }
        }
    

    Ist das gleiche - nur in grün (bzw. string);



  • int und long sind structs, also ist die nicht-Änderung okay.
    Bei string s ist das wie in Java. s="bla" erzeugt ein neues Objekt, da man einen string nach dem Erstellen nicht mehr ändern kann (StringBuilder hingegen würde wie erwartet ändern).



  • void Foo(object x) //x ist eine _Kopie der Referenz_ auf den übergebenen Parameter 
    {
       x = new object();
    }
    
    ...
    object myObj, otherObj;
    myObj = otherObj = new object();
    
    Foo(myObj);
    
    System.Diagnostics.Debug.Assert(myObj == otherObj);
    

    Ansonsten kann man schreiben

    void Foo(ref object x)
    //oder
    void Foo(out object x)
    


  • Knuddlbaer schrieb:

    ...
    Hier wird eine Kopie der Referenz erzeugt. Die Kopie der Referenz wird auf einen neuen Wert gesetzt.
    ...

    👍
    Ich war zu langsam. Aber wer hätte gedacht, dass vor acht Uhr noch andere Leute posten.



  • im fall von string wird die referenz kopiert - der kopie dann ein neuen wert zugewiesen
    dieser verfaellt nach ende der sichtbarkeit
    soweit kann ich das unterschreiben - die tests haben das auch ergeben
    nur

    _wonach_ kann cih gehen ? Int32, String sind alles genauso klassen wie eigene
    warum werden diese kopiert uebergeben aber eigene klassen nicht??
    das ist gerade das problem - beim entwickeln weiss man nicht unbedingt wie der wert an kommt - und da muss man manchmal echt aufpassen
    ich hab bisher kein gemeinsamen tonus erkennen koennen

    // nicht geaendert

    static void Change(string value)
    {
    	value = "neu";
    	Console.WriteLine(value);
    }
    
    static void Main(string[] args)
    {
    	string value = "begin";
    	Console.WriteLine(value);
    	Change(value);
    	Console.WriteLine(value);
    }
    

    // geaendert

    class Value
    {
    	public string Text;
    	public Value(string value)
    	{
    		Text = value;
    	}
    }
    static void Change(Value value)
    {
    	value.Text = "neu";
    	Console.WriteLine(value.Text);
    }
    static void Main(string[] args)
    {
    	Value value = new Value("begin");
    	Console.WriteLine(value.Text);
    	Change(value);
    	Console.WriteLine(value.Text);
    }
    

    ersteres wird also kopierte referenz uebergeben welches verfaellt - zweiteres wird als "echte" referenz uebergeben
    woran kann man den unterschied festhalten ? sind beides klassen!

    @Any Mod, koennte man diese diskusion in einen eigenen thread splitten?



  • Mr Evil schrieb:

    // nicht geaendert

    static void Change(string value)
    {
    	value = "neu"; //Setzt die Referenz auf ein neues Objekt
    	Console.WriteLine(value);
    }
    ...
    // geaendert
    static void Change(Value value)
    {
    	value.Text = "neu"; //setzt eine Property des Objektes auf neues Objekt
    	Console.WriteLine(value.Text);
    }
    

    Mr Evil schrieb:

    ersteres wird also kopierte referenz uebergeben welches verfaellt - zweiteres wird als "echte" referenz uebergeben
    woran kann man den unterschied festhalten ? sind beides klassen!

    Es ist beides gleich. nur das erste mal erzeugst du ein neues Objekt und weist es der Referenz zu und das andere Mal benutzt du die Referenz um eien Property des Objektes zu setzten.



  • Wir sollten die Diskussion an dieser Stelle abbrechen und auf die Grundlagen Literatur verweisen. Bisher ist an Erkenntnissen wenig bis nix angekommen.

    Die Unsicherheit werden wir wohl nicht ausdiskutieren können.



  • @hajb
    ich glaub ich versteh - wenn ich
    value.Text = "neu"; mit
    value = new Value("neu"); ersetz, ist es das selbe verhalten wie beim string
    also weise der referenz ein neuen wert zu - dh die referenz zeigt auf ein neues objekt (eher vergleichbar mit c++ pointern bla = &object;)

    koennte man nicht sagen: der wert wird nicht geaendert sobald man der referenz direkt etwas zuweist? zuweisung per = sowie aehnlichen operatoren wie += *= usw ??
    oder noch simpler das man diese kopierte referenz mit c++ pointern vergleicht?



  • noch simpler das man diese kopierte referenz mit c++ pointern vergleicht?

    Streich das kopierte und es passt.


Anmelden zum Antworten