C# Problem mit Dictionary<string, struct>

Thaxll'ssillyia

Captain
Registriert
Dez. 2007
Beiträge
3.501
Hi Community!

Ich habe ein Problem mit einer Dictionary mit Key string und Value struct.

So sieht mein Code aus:

Code:
    public partial class Form1 : Form
    {
        struct Channel
        {
            static string titel;
            static string admin;
            static string pw;
            public Channel(bool SetEmpty)
            {
                if (SetEmpty == true)
                {
                    titel = null;
                    admin = null;
                    pw = null;
                }
            }
            public static string[] Refresh()
            {
                string[] Out = new string[3];
                Out[0] = titel;
                Out[1] = admin;
                Out[2] = pw;
                return Out;
            }
            public string Titel
            {
                get { return titel; }
                set { titel = value; }
            }
            public string Admin
            {
                get { return admin; }
                set { admin = value; }
            }
            public string PW
            {
                get { return pw; }
                set { pw = value; }
            }
        }
        static Dictionary<string, Channel> ChannelList = new Dictionary<string, Channel>(); 
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string ChannelName = textBox1.Text;
            Channel I = new Channel(true);
            I.Titel = textBox2.Text;
            I.Admin = textBox3.Text;
            I.PW = textBox4.Text;
            ChannelList.Add(ChannelName, I);
            listBox1.Items.Clear();
            listBox1.Items.AddRange(Channel.Refresh());
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();
            textBox4.Clear();
            RefreshListView();
        }
        void RefreshListView()
        {
            listView1.Items.Clear();
            foreach (string ChannelName in ChannelList.Keys)
            {
                Channel I = ChannelList[ChannelName];
                listView1.Items.Add(ChannelName);
                listView1.Items[listView1.Items.Count - 1].SubItems.Add(I.Titel);
                listView1.Items[listView1.Items.Count - 1].SubItems.Add(I.Admin);
                listView1.Items[listView1.Items.Count - 1].SubItems.Add(I.PW);
            }
        }
    }

Problem ist, wenn ich einen 2. Eintrag hinzufüge, erhält der erste auch diesen Wert (Programm zum Testen im Anhang).

Was mache ich falsch? Vielen Dank für Hilfe!

Gruß Thax
 

Anhänge

  • DictionaryTest.rar
    5 KB · Aufrufe: 136
Lösung is ja ganz einfach:
static string titel;
static string admin;
static string pw;

Warum sollen die bitte static sein? oO
 
Zuletzt bearbeitet:
Weil sonst das kommt:

An object reference is required for the non-static field, method, or property

Hab dann kein Zugriff mehr auf diese Variablen.

Ich lad das ganze Prog hoch. Jetzt im Anhang.

Mein Problem ist halt, das beim erneuten hinzufügen zu einer Dictionary alle vorangehenden Werte den neuen annehmen
 

Anhänge

  • DictionaryTest.rar
    40,6 KB · Aufrufe: 155
Weißt du überhaupt, was das static heißt?
Das kann so nicht funktionieren.

Das Problem liegt damit in Refresh...

Was spricht dagegen:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DictionaryTest
{
    public partial class Form1 : Form
    {
       struct Channel
        {
           string titel;
           string admin;
           string pw;

            public Channel(String _titel, String _admin, String _pw)
            {
                titel = _titel;
                admin = _admin;
                pw = _pw;
            }

            public string[] ToStrings()
            {
                string[] Out = new string[3];
                Out[0] = titel;
                Out[1] = admin;
                Out[2] = pw;
                return Out;
            }

            public string Titel
            {
                get { return titel; }
                set { titel = value; }
            }
            public string Admin
            {
                get { return admin; }
                set { admin = value; }
            }
            public string PW
            {
                get { return pw; }
                set { pw = value; }
            }
        }
        static Dictionary<string, Channel> ChannelList = new Dictionary<string, Channel>(); 
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string ChannelName = textBox1.Text;
            Channel I = new Channel(textBox2.Text, textBox3.Text, textBox4.Text);
            ChannelList.Add(ChannelName, I);
            listBox1.Items.Clear();
            listBox1.Items.AddRange(I.ToStrings());
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();
            textBox4.Clear();
            RefreshListView();
        }
        void RefreshListView()
        {
            listView1.Items.Clear();
            foreach (string ChannelName in ChannelList.Keys)
            {
                Channel I = ChannelList[ChannelName];
                ListViewItem li = new ListViewItem(ChannelName);
                li.SubItems.Add(I.Titel);
                li.SubItems.Add(I.Admin);
                li.SubItems.Add(I.PW);
                
                listView1.Items.Add(li);
            }
        }
    }
}
 
Zuletzt bearbeitet:
Weißt du überhaupt, was das static heißt?

Ich muss zugeben, nein. Ich setzt es einfach davor, um Zugriff zu erhalten.
hat bis jetzt auch immer geklappt.

Bist du sicher, das das static was mit dem fehlerhaften hinzufügen zur Dictionary hat?
 
JA!

Lies dir bitte noch mal durch was "static" bewirkt, denk drüber nach und dann guck dir deinen Code mal an. ;)


... bitte bewusst proggen und nicht nur einfach was machen nur das es dann funktioniert (hier Zugriff gibt).
 
ich zitier mal das fachchinesisch:

Mit dem static-Modifizierer kann ein statischer Member deklariert werden, der zum Typ selbst und nicht zu einem bestimmten Objekt gehört.

So richtig schlau werd ich daraus aber nicht...

@mib: Danke, das funzt.
wie ich auf das static gekommen bin, weiß ich auch nicht.

Ich arbeite in meinem (richtigen) Programm mit einer extra Klasse, wo ich globale Variablen definiere.
Vermutlich deswegen

PS: Und wieso muss die Dictionary dann statisch sein?
 
Zuletzt bearbeitet:
Static bedeute das dieser Member für alle Objekte der Klasse gültig ist und nicht zur einem spezifischen Objekt gehört. Jedes Objekt der Klasse(du solltest sowieso lieber eine Klasse benutzen und kein struct) kann auf diesen statischen Member zugreifen, aber auch jedes OBjekt der klasse erhält die selben Werte wenn es auf den Member zugreift.
 
Ähm muss nicht sein, kann sein - ka wie du es haben willst... ich habs halt einfach gelassen wie es war...
 
Ich hab jetzt die Klasse Channel und die Dictionary<string, Channel> in eine eigene Klasse ausgelagert, wie greif ich nun ohne static darauf zu?
Code:
    class Data
    {
        public Dictionary<string, Channel> ChannelList = new Dictionary<string, Channel>();
    }
    class Channel
    {
        string titel;
        string admin;
        string pw;

        public string[] ToStrings()
        {
            string[] Out = new string[3];
            Out[0] = titel;
            Out[1] = admin;
            Out[2] = pw;
            return Out;
        }
        public string Titel
        {
            get { return titel; }
            set { titel = value; }
        }
        public string Admin
        {
            get { return admin; }
            set { admin = value; }
        }
        public string PW
        {
            get { return pw; }
            set { pw = value; }
        }
    }

Form1:

Code:
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Data Daten = new Data();
            string ChannelName = textBox1.Text;
            Channel I = new Channel();
            I.Titel = textBox2.Text;
            I.Admin = textBox3.Text;
            I.PW = textBox4.Text;
            Daten.ChannelList.Add(ChannelName, I);
            listBox1.Items.Clear();
            listBox1.Items.AddRange(I.ToStrings());
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();
            textBox4.Clear();
            RefreshListView();
        }
        void RefreshListView()
        {
            Data Daten = new Data(); //geht nicht, erhalte nicht den aktuellen Dictionary-Wert
            listView1.Items.Clear();
            foreach (string ChannelName in Daten.ChannelList.Keys)
            {
                Channel I = Daten.ChannelList[ChannelName];
                ListViewItem li = new ListViewItem(ChannelName);
                li.SubItems.Add(I.Titel);
                li.SubItems.Add(I.Admin);
                li.SubItems.Add(I.PW);

                listView1.Items.Add(li);
            }
        }
 
Du erstellst die Variable "Daten" bei jedem Klick und bei jedem Refresh neu. Du musst sie stattdessen zu einer Membervariable von Form1 machen.
 
Code:
class Form1 
{
    Data Daten;
    public Form1
    {
        InitializeComponent();
        Daten = new Data();
    }
    ... 
}
 
class Form1
{
Data Daten;
public Form1
{
InitializeComponent();
Daten = new Data();
}
...
}

Wenn ich das jetzt aber so mache:
Code:
    public partial class Form1 : Form
    {
        Data Daten;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Daten = new Data();
            string ChannelName = textBox1.Text;
            Channel I = new Channel();
            I.Titel = textBox2.Text;
            I.Admin = textBox3.Text;
            I.PW = textBox4.Text;
            Daten.ChannelList.Add(ChannelName, I);
            ...
        }
        void RefreshListView()
        {
            Daten = new Data();
            ...
        }
    }

erhalte ich bei RefreshListView mit Daten = new Data(); wieder einen leeren Array.
 
Du musst das nur noch einmal initialisieren. Also "Daten = new Data()" kommt in den Konstruktor. Die anderen Aufrufe von "Daten = new Data()" musst du entfernen.
 
ahh, vielen Dank! Jetzt klappts.

Und wie ist das, wenn jetzt eine andere Form mit einem anderen Thread zwischendrin was verändert, ändert sich der Wert der Membervariable mit?

Gruß Thax
 
Also wenn du jetzt eine neue Form aufrufst und ihr die Variable "Daten" übergibst, kann auch diese Form Änderungen daran vornehmen, die dann für beide sichtbar sind.
 
@Thaxll'ssillyia: Du solltest dir mal dringend die Grundlagen von C# angucken, besonders was Klassen, Objekte, Deklarieren, Initialiseren angeht. Ohne diese Grundlagen bringt es dir recht wenig, großartig tolle GUIs zu bauen, wenn der Code dahinter Wurst ist.
 
Und wenn das sitzt, was toeffi gesagt hat, solltest du auch drüber nachdenken, deinen Steuerelementen aussagekräftige Namen zu geben. Weil "TextBox1" usw. sagen nicht gerade aus was sie in der GUI für eine Rolle spielen.

Jedoch stimme ich da toeffi voll und ganz zu, die Grundlagen sollten sitzen!
 
Ok, ich werd mich kümmern.:)

Edit: So, ich hab jetzt mein komplettes Programm umgestellt auf Membervariablen, nur hab ich mit einer Sache ein Problem:

Von einer Klasse aus rufe ich Form1.Invoke auf.
Mit Übergabeparametern hat das bisher immer geklappt.
Allerdings will ich diesmal einen Rückgabewert bekommen, wie mache ich das?

Code:
namespace Chat_Server
{
    class Data
    {
         Variables Vars;
         Vars = Instanz.Main.Invoke(new CallbackVariables(Instanz.Main.RecieveVariables));
         //funtioniert nicht
    }
    delegate Variables CallbackVariables();
    public partial class Main : Form
    {
        Variables Vars;
        public Variables RecieveVariables()
        {
            return Vars;
        }
    }
    public class Variables
    {
         //Variablen
    }
}
 
Zuletzt bearbeitet:
Zurück
Oben