Laden...
F
fortuneNext myCSharp.de - Member
Student Informatik RWTH Aachen Aachen Dabei seit 07.07.2009 45 Beiträge
Benutzerbeschreibung

Forenbeiträge von fortuneNext Ingesamt 45 Beiträge

19.06.2015 - 11:31 Uhr

Was mich daran stört, ist, dass ich im Prinzip immer an zwei Stellen Code einfügen muss statt nur an einer. Auch wenn es im Using-Fall nur eine Klammer am Ende der Funktion ist. Die implizite Zerstörung von Objekten wie in C++ benötigt das nicht.

19.06.2015 - 00:10 Uhr

Hi,

habe das alles mal durchgelesen.
Im Prinzip würde using das ja genau tun, ich finds aber immernoch nicht schön, denn die gebenchmarkte Methode müsste komplett im Usingblock sein oder ich müsste das Objekt am Ende explizit disposen. Geht das nicht automatisch, wenn die Funktion fertig ausgeführt ist?

18.06.2015 - 22:47 Uhr

Hallo,

ich möchte im Moment einen Microbenchmark für eine Funktion schreiben.

Aktuell tue ich das so:

            Console.WriteLine(@"Calling " + System.Reflection.MethodBase.GetCurrentMethod().Name + @"...");
            var stopWatch = new Stopwatch();
            stopWatch.Start();
            try
            {
//...
// if... return
// if... return
            }
            finally
            {
                stopWatch.Stop();
                Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name + @" took " + stopWatch.Elapsed);
            }

Finally ist nötig, weil zwischendurch viele Returns drin vorkommen.
Ich finde das irgendwie unschön. In C++ könnte man ein Benchmarkobjekt erstellen, dass im Constructor den Counter startet und im Destruktor beendet und ausgibt - da das Objekt am Ende der Methode sofort zerstört würde, würde also sofort der Destruktor auslösen. Eine sehr schöne Methode, da man nur am Anfang das Benchmarkingobjekt zu erstellen brauch und sich dann um nichts mehr kümmert.
Leider geht das in Managed Sprachen natürlich wegen dem GC nicht, das Objekt wird nicht unbedingt sofort zerstört. In Java kann man das "autodisposable"-Interface verwenden, um Objekte sofort zu zerstören, wenn sie keine Referenzen mehr haben - geht soetwas auch in C#?

Viele Grüße
fortuneNext

16.01.2014 - 14:04 Uhr

Tatsächlich, das hat die Lösung gebracht. Vielen vielen Dank!

15.01.2014 - 22:51 Uhr

Ha, habe doch alles nötige hier.

Also nach dieser Methode zum Laden bekomme ich die Exceptions:

Fehlermeldung:
{"<ArrayOfXmlAccount xmlns=''> wurde nicht erwartet."}

bzw.> Fehlermeldung:

Das Objekt des Typs "Aktivenkasse.XmlAccount[]" kann nicht in Typ "System.Collections.Generic.List`1[Aktivenkasse.XmlAccount]" umgewandelt werden.

15.01.2014 - 22:44 Uhr

Hi,

kann es grade nicht ausprobieren, werde ich morgen tun.
Allerdings frage ich mich, warum er dann die Datei korrekt schreibt und nur beim Lesen ausgerechnet nur dieses eine Feld leer bleibt, alle anderen aber wunderbar funktionieren?
(Die Attribute hab ich übrigens eingefügt, weil der Compiler mir das so gesagt hat. 😃 )

Gruß
fortuneNext

15.01.2014 - 20:58 Uhr

Hi,

Entschuldigung, das wäre natürlich sinnvoll gewesen! Da die Klassen recht trivial sind, hatte ich das fälschlicherweise als irrelevant angenommen. Mein Fehler.

Hier die beiden Definitionen:

[XmlInclude(typeof(XmlStructuralAccount)), XmlInclude(typeof(XmlValueAccount))]
    public abstract class XmlAccount
    {
        public string Name { get; set; }

        public AccountTypes AccountType { get; set; }
    }

[XmlInclude(typeof(List<String>))] // brauch ich das überhaupt? klappt ohne auch nicht
    public class XmlStructuralAccount : XmlAccount
    {
        public List<string> Subaccounts;

        public XmlStructuralAccount() { }

        public XmlStructuralAccount(StructuralAccount origin)
        {
            Name = origin.Name;
            AccountType = origin.AccountType;
            Subaccounts = new List<string>();
            foreach (Account account in origin.Subaccounts)
            {
                Subaccounts.Add(account.Name);
            }
        }
    }

Ich denke, die anderen beiden Klassen sind wirklich irrelevant.

Gruß
fortuneNext

14.01.2014 - 20:18 Uhr

verwendetes Datenbanksystem: <XML>

Hallo,
ich bin es gleich nochmal.

Ich habe ein Problem mit dem Deserialisieren einer sich in einem Objekt befindlichen List<string>.

Meine Klasse XmlStrucutralAccount enthält eine List<string>. Ich möchte sie mit einem XmlSerializer serialisieren. Folgende Datei ist die Ausgabe meines Beispielsets:

<?xml version="1.0"?>
<ArrayOfXmlAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>AktivKonto</Name>
    <AccountType>Active</AccountType>
    <StartValue>150</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>PassivKonto</Name>
    <AccountType>Passive</AccountType>
    <StartValue>-15</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlUserAccount">
    <Name>User</Name>
    <AccountType>User</AccountType>
    <StartValue>0</StartValue>
    <Email>test@mail.de</Email>
  </XmlAccount>
  <XmlAccount xsi:type="XmlStructuralAccount">
    <Name>Strukturkonto</Name>
    <AccountType>Active</AccountType>
    <subaccounts>
      <string>AktivKonto</string>
      <string>PassivKonto</string>
      <string>User</string>
    </subaccounts>
  </XmlAccount>
</ArrayOfXmlAccount>

Dabei kann man unter dem 4. Punkt sehen, dass die Liste <subaccounts> korrekt serialisiert wird.
Beim Deserialisieren bleibt die Liste "subaccounts" jedoch leer! Alles andere wird absolut korrekt eingelesen. Was könnte ich falsch gemacht haben?

Weitere Informationen: XmlStructuralAccount ist eine Unterklasse von XmlAccount (abstract), ebenso XmlValueAccount. XmlUserAccount ist wiederum eine Unterklasse von XmlValueAccount. Ich habe jeweils [XmlInclude(typeof(Unterklasse(n))] vor die Klassen gesetzt, weitere [] Attribute habe ich nicht gesetzt.
Kommandos, die ich benutze:

XmlSerializer serializer = new XmlSerializer(typeof(List<XmlAccount>)); // zum schreiben
List<XmlAccount> xmlAccounts = (List<XmlAccount>)serializer.Deserialize(streamReader); // zum lesen

Insgesamt handelt es sich also um eine List<Account>, die serialisiert werden soll.

Ich habe die Vermutung, dass ich vielleicht irgendwelche Attribute fehlen? Aber warum wird die Datei dann korrekt geschrieben, jedoch nicht gelesen?

Vielleicht hat ja jemand eine Idee. 😃
Freundliche Grüße
fortuneNext

14.01.2014 - 19:31 Uhr

Hi,

alles klar, vielen Dank! So ungefähr war auch meine alte Lösung. Ich hatte allerdings gehofft, dass man irgendwie den XmlSerializer verwenden kann. Den habe ich nämlich jetzt zwar verwendet, allerdings muss ich genau das, was du schreibst, trotzdem tun, und ich hatte gehofft, dass es eine direktere Anweisung gibt. 😃

In jedem Fall, vielen Dank!

14.01.2014 - 17:31 Uhr

Dann hast du den Namen als eindeutigen Bezeichner, also sollte es ohne Probleme funktionieren, wo genau liegt dein Problem?

Hallo MrSparkle,

ich frage mich, wie ich C# beibringe, das zu tun! Also, nur ein Feld des Objektes b als Attribut von a zu speichern statt das ganze Objekt b, und bei der Deserialisierung meine Zuordnungsfunktion zu verwenden. 😃 Tschuldigung, das hätte ich natürlich dazuschreiben sollen!

14.01.2014 - 16:25 Uhr

verwendetes Datenbanksystem: <XML>

Hallo,

ich verwende neuerdings das erste mal XML-Serialisierung und möchte nun Objekte speichern. Vereinfacht habe ich eine Klasse A, die eine Referenz auf ein Objekt der Klasse B enthält, sowie eine Klasse B, die einen Namen als Feld hat.
Habe ich nun ein Objekt b vom Typ B und ein Objekt a vom Typ A, das auf b referenziert, existieren nach der Deserialisierung natürlich zwei gleiche Objekte des Typs B. Es kommt jedoch nicht in Frage, b nicht zu serialisieren.

Zu dem Problem habe ich bereits folgendes gefunden:
.net XML Serialization - Storing Reference instead of Object Copy

Die dort vorgeschlagene Lösung scheint mir jedoch mit Kanonen auf spatzen geschossen, denn das Feld "Name" aus Klasse B ist in meiner Datenstruktur eindeutig. Es würde mir also reichen, wenn zu jedem Objekt a der Name des referenzierten Objekts b gespeichert würde. Zur Deserialisierung müsste dann eine bereits existierende Funktion aufgerufen werden können, die aus dem Namen wieder das Objekt macht.

Gibt es hierfür eine schöne Lösung?

Liebe Grüße
fortuneNext

17.06.2011 - 18:16 Uhr

Hi!

Ich möchte gerne auf einer Website (html) über ein Programm Daten in Felder eintragen und andere Elemente, wie etwa Buttons, manipulieren.
Meine Frage ist der grundsätzliche Ansatz: Was brauche ich dafür, um jetzt tatsächlich an die Elemente einer Website zu kommen?

Gruß
fortuneNext

23.07.2010 - 23:12 Uhr

Nun gut, schade.
Danke!

PS: Ich hoffe ja auf deine Signatur 😄

23.07.2010 - 22:49 Uhr

Hallo,
ich habe 2 Funktionen:

public List<String> Request(string request, string mode, int depth)

public string Request(string request, string mode, int depth)

Fehlermeldung:

Type 'Mind' already defines a member called 'Request' with the same parameter types

Wie kriege ich das hin, dass ich die beiden trotzdem so überladen kann? Wenn ich einfach einen total nutzlosen Parameter bei einem einfüge, funktionierts, aber das kanns ja nicht sein.

Gruß
fortuneNext

21.07.2010 - 21:00 Uhr

Tatsache, das mit dem Standartconstrucot war das Problem. Gelöst. Danke! =)

21.07.2010 - 18:09 Uhr

verwendetes Datenbanksystem: <XML>

Hallo,
ich bemühe mich im Moment darum, die Sache mit der Serialization zu erlernen.

Folgende klasse habe ich geschrieben:

    [XmlRoot ("mind")]
    public class Mind
    {
        public class node
        {
            public node(string Name) {} //GEKÜRZT

            public node(string Name, List<connection> Connections) {}  //GEKÜRZT

            public class connection
            {
                public connection(string Name, int Power){ } //GEKÜRZT

                [XmlAttribute ("name")] public string Name;
                [XmlAttribute ("power")] public int Power;
            }

            public string Name;
            [XmlElement("connection")] public List<connection> Connections = new List<connection>();
        }

        [XmlElement("node")] public List<node> Nodes = new List<node>();
        public int InitialAmouth = 0;
        public int AddAmouth = 100;
        public int DecAmouth = 1;
    }

Zum Speichern in die XML Datei wollte ich verwenden:

        XmlSerializer xs = new XmlSerializer(typeof(Mind));
        TextWriter tw = new StreamWriter(pfad);
        xs.Serialize(tw, Minds[ID]);
        tw.Close();

Jedoch gibts beim typeof(mind) das Problem:

There was an error reflecting type 'Brain.Mind'.

Woran liegts? Ich vermute, dass es damit zu tun haben könnte, dass ich versuche, "connection" zu serialisieren, obwohls nur in einer Klassendeklaration vorkommt. Wie würde ich das denn dann richtig machen?

Gruß
fortuneNext

11.04.2010 - 21:34 Uhr

verwendetes Datenbanksystem: <XML>

Hallo,
Ich eigentlich eine XML-Datei, in der Charaktere mit Werten gespeichert sind:

<?xml version="1.0" encoding="utf-16"?>
<Characters>
  <HansPeter>
    <eKG>12</eKG>
    <eBF>13</eBF>
    <eGE>14</eGE>
    <eWI>15</eWI>
    <eST>16</eST>
    <eWK>17</eWK>
    <eIN>18</eIN>
    <eCH>19</eCH>
    <eLEB>20</eLEB>
    <eATT>21</eATT>
    <eSkills>
      <Fertigkeit 1 />
      <Fertigkeit 2 />
      <Fertigkeit 3 />
    </eSkills>
    <eTalents>
      <Talent 1 />
      <Talent 2 />
      <Talent 3 />
    </eTalents>
  </HansPeter>
</Classes>

Ich will jetzt einen Editor schreiben, mit dem ich einfach weitere Charaktere in diese Struktur einfügen kann. Falls der einzufügende Charakter schon existiert, soll er einfach überschrieben werden.

StringWriter SaveString = new StringWriter();
StreamWriter SaveDatei = new StreamWriter(Path.GetDirectoryName(Application.ExecutablePath) + "\\classes.dat");
XmlTextWriter myXmlTextWriter = new XmlTextWriter(SaveString);

//Langer Codeblock, der mit WriteStartElement etc die XML-Datei über den XmlTextWriter baut

SaveDatei.Write(/*verschluesselung.Crypt(*/SaveString.ToString())/*)*/;
SaveDatei.Flush();
SaveDatei.Close();

So habe ichs bisher versucht. Der StreamWriter schreibt dann am Ende einfach den StringWriter auf die Festplatte. So wird aber leider immer wieder die Datei neu erzeugt, statt die alte zu erweitern. Gibt es eine relativ einfache Möglichkeit, das zu ändern, z.B. indem der XMLTextWriter statt das ganze Dokument nur einen einzelnen Knoten beschreibt?
Den Anfang, die Datei von der Festplatte erstmal in ein XmlDocument zu laden, habe ich schon fertig geschrieben, kein Problem. Aber wie verbinde ich die beiden Komponenten jetzt?
Die Zeit ist leider ein bischen knapp, habe leider das Informatikprojekt für die Schule etwas verpennt, wegen Abiturvorbereitungen X_X
Gruß
fortuneNext

27.02.2010 - 16:48 Uhr

Ja, dass der Tippen des Quellcodes ein relativ geringer Anteil, darüber bin ich mir völlig im Klaren. Es ist sogar eher das Ergründen der Zusammenhänge, die mich interessieren. Tatsächlich lese ich auch ziemlich oft in der MSDN, so ziemlich für alle jemals verwendeten Komponenten (hauptsächlich außerhalb der Netzwerkprogrammierung). Es ist eine ziemlich gute Dokumentation, die viele Probleme schon löst, bevor sie auftauchen; sowas gibts in vielen anderen Sprachen leider nicht oder nur unzureichend.
Die Lernmethodik, mit der ich bisher am meisten Erfolg hatte, war allerdings, vorher zu wissen, wo das, was ich mir durchlese, eigentlich hinführt. Ich arbeite mich jetzt nach und nach durch die genaue Funktion des TCPClients- und Listeners, lese mir den Streamreader/Writer und die generelle Networkstream / Streamklasse durch und vieles mehr. Wo ich jetzt weiss, wo das ganze eigentlich hinführt und was ich alles brauche, fällt das auch längst nicht mehr so schwer.

Was den Streamreader/Streamwriter angeht - ich gehe mal davon aus, dass Du weißt was die MSDN ist, oder ? Hättest Du da den Begriff im Index eingetippt, hättest Du sofort alle Informationen zusammen gehabt. Selbst wenn Du "Streamreader" bei google eintippst führt sofort der erste Eintrag zur entsprechenden MSDN-Seite.

Ich weiss jetzt nicht genau, worauf sich das bezieht. Über meine Mutmaßung über den Streamreader/writer in meinem vorherigen Post? Da wollte ich ja eigentlich bewusst erstmal schreiben, wie ichs mir vorstelle, bevor ich in die MSDN gucke. Vorher habe ich das nicht getan, weil ich da noch nichtmal eine konkrete Sammlung der Sachen hatte, die ich tatsächlich brauche und http://msdn.microsoft.com/de-de/library/system.io.streamreader%28VS.80%29.aspx fand ich völlig ohne Ahnung jetzt nicht so besonders hilfreich. Mittlerweile verstehe ich, wie ich die Klasse einsetze und verstehe dadurch auch besser, was mir dort mitgeteilt wird.

Naja, aber ich denke im Endeffekt weiss ich jetzt wies funktioniert, vielleicht muss ich tatsächlich noch lernen ein bischen mehr Tipps von Erfahreneren anzunehmen =)
Gruß
fortuneNext

26.02.2010 - 20:09 Uhr

Sorry, aber ich weiß echt nicht was Du erwartest. Das hier ist ein Forum, keine Programmierschule.

Also ich hätte einfach mit dem einfachst möglichen Programm geantwortet und auf die zugrundeliegenden Elemente hingewiesen, die für ein intensives Verständniss erforderlich sind.

Das Du noch selbst in die MSDN gehen und dort StreamReader eintippen musst, um den Namespace rauszufinden (wobei ich ihn sogar dazugeschrieben hab) sollte eigentlich für einen Gymnasiasten kein unüberwindbares Hindernis darstellen

haha, ich hatte bloß aus irgendeinem Grund gedacht dass ich schon einen StreamReader im TCP-Client/Listener finde...

Eigentlich hatte ich versucht damit auszudrücken, dass ich einen logischen Denkfehler gemacht habe. Das hatte absolut garnichts mit einem falsch deklarierten Namespace zu tun. Um mein Zitat auch nochmal gründlich zu erklären, ich hatte in Richtung myTCPClient.Streamreader() oder myTCPClient.getStreamReader() oder ähnliches gedacht. Hier sieht man schonwieder das zum Teil mangelhafte Eindenkungsvermögen in Anfänger: Tatsächlich wäre keinem der Gymnasiasten, die ich kenne und die nicht schon länger mit C# zutun haben, sofort aufgefallen, dass der Name des Namespaces darauf hinweist, dass der Streamreader kein Teil des Clients ist. In Delphi z.B. gabs garkeine Namespaces. Wenn ich so im Nachhinein drüber nachdenke, ists natürlich klar, aber die Versuche eines Anfängers sehen dann ca so aus:


myTCPListener.getStream().WriteLine("Hallo";);
myTCPClient.StreamWriter(getStream()).WriteLine("Hallo";);
NetworkStream myStream = new NetworkStream(myTCPClient);
StreamWriter myStream = new Streamwriter (myTCPListener);
TCPClient myTCPClient = new TCPClient (myTCPListener.getStream());
myTCPListener.Accept().WriteLn("Hallo";);
myTCPListener.AcceptTCPClient();

und ähnlicher Unfug. Für Anfänger ist es garnicht so selbstverständlich, wie man jetzt den Stream in den Writer/Reader kriegt o.ä.
Mag sein dass ich hier mehr Hilfe bekommen habe als in anderen Foren, aber ich wollte jetzt auch nicht sagen dass das Forum hier doof ist, sondern generell die Probleme von Anfängern darlegen. Oft wird eben nicht erkennt, was für einen Anfänger alles nicht selbstverständlich ist.

Wenn Du Informatik studieren willst, musst Du als allererstes lernen, dass es an der Uni niemanden gibt, der Dir alles fertig vorgekaut auf dem Teller präsentiert. Da sitzt Du mit paar hundert anderen Studenten im Hörsaal und es kennt so ziemlich niemand überhaupt Deinen Namen. Und ob Du da irgendwas verstehst oder nicht, ist alleine Dein Problem. Du wirst da noch oft froh sein, dass es solche Tutorials wie die von Dir aufgezählten überhaupt gibt, zu meiner Zeit an der Uni hieß es da noch ohne Hilfe durchbeißen.

Da stimme ich wohl zu. Ich bin jetzt eigentlich auch schon froh über solche Tutorials, weil ohne die wirds erst recht schwierig. Aber um ehrlich zu sein glaube ich, viele Studenten tauschen sich gerade im Fach Informatik über Internetforen aus und helfen sich gegenseitig. Und ich glaube, es ist etwas dran vorbeiargumentiert, wenn ich Profis zu mehr Verständniss gegenüber Anfängern aufrufe, darauf hinzuweisen, dass man auf dem Weg zum Profi eben keine Hilfe kriegt (weil diese oft kein Verständniss für Anfänger haben).

Solche "Informatiklehrer" soll es geben, das stimmt. Es gibt sogar viele Lehrer, die einfach falsche Grundlagen vermitteln und auf diese Weise dazu beitragen das die Schüler die Konzepte nicht richtig begreifen.

Und davon nicht wenige.
Problem sind aber auch nicht nur die Lehrer, sondern auch die Landesfach"kompetenzen". Ihr solltet euch mal die total seltsam zusammengebastelten, auf deutsch programmierten Pseudoklassen angucken, um Schülern Dinge wie Queues, Stacks, Listen oder Trees beizubringen. Da wird man nichtmal schlau draus, wenn man sich auskennt. Unnötig kompliziert, total an der Realität und Effizienz vorbei. Das Bildungssystem in Informatik, zumindest auf der Schule, ist in einem furchtbaren Zustand. Ich habe die leise Befürchtung, dass Unis genauso technisch zurückgeblieben sind, aber ich hoffe mal das Gegenteil.

Kann ich nachvollziehen. Aber mal ehrlich, diese Zeilen findest du auch in dem von Joetempes verlinkten Tutorial. Der Unterschied ist, du benutzt hier eine überliegende Klasse, statt direkt Sockets zu nutzen.

Ja, schon. Wenn man weiss wonach man sucht, klappt das. Das Problem ist auch, in vielen Tutorials vorher wurde die schon benutzt. Dann wieder was Anderes; das gibt im Kopf schnell mal einen unklaren Ballen an Informationen. Dabei sucht man eigentlich bloß erstmal eine kurze, einfache, funktionierende Methode. Dann kann man sich auch die anderen anschauen. Wenn mann dann noch die Argumentbearbeitung durchschauen muss, weiss man irgendwann garnicht mehr, was jetzt alles benötigt ist und was wozu gehört. Da fragt man am liebsten einfach kurz Leute, dies dir definitiv beantworten können, und dann kanns auch losgehen mit dem Verständniss anderer Methoden und den sonstigen Behandlungen im Programm.

Dann müsstest du sagen, du benötigst schnelle Hilfe und kannst dich nicht mit den Grundlagen befassen, weil du Ziel XY erreichen willst.

Dir ist natürlich bewußt, dass du ein generelles Problem hast, wenn du dich nicht richtig mit den Details befasst. Du verfügst dann über gefährliches Halbwissen. Zum Beispiel kann ich dir die Frage stellen, was Flush() bewirkt und warum es bei einem StreamWriter funktioniert, bei einem NetworkStream aber nicht.

Hm, naja, das ist eine Frage der Lernmethodik. Ich denke eigentlich, man kann durchaus auch erstmal Code benutzen, den man nicht 100% versteht und dann später ergründen, was man da eigentlich genau tut. Quasi eben nicht die Theorie der Praxis vorrausschicken, sondern beides machen.
Flush() schickt soweit ich weiss den Buffer einfach ab. Das ist glaube ich bei Writerklassen so üblich - diese "sammeln" quasi erstmal was hereingeschrieben wird und schickens dann erst beim Flush() ab. Genau weiss ichs tatsächlich nicht, ich leite es mir grade vom XMLWriter ab, wo man auch den Flush() braucht. Und der Networkstream ist entsprechend nicht so eine Klasse die zuerst sammelt, sondern einfach das wo direkt reingeschrieben wird. Der Stream ist denke ich wie ein Textblock auf der Festplatte, ein Writer sowas wie ein Editor, der erst die Daten auf die Platte überträgt wenn du auf "SPEICHERN" drückst.

So tragisch ist der Code auch wieder nicht. Ein wenig Exception Handling ist dabei, ansonsten dasselbe in weiß.

Naja, inzwischen versteh ich ihn auch, nachdem ich raushatte was eigentlich die ausführenden Zeilen sind. Nur wenn man eben überhaupt keine richtige Ahnung hat, ist die Formulierung

 while ((bytesRcvd = client.Receive(rcvBuffer, 0, rcvBuffer.Length,
SocketFlags.None)) > 0) {
client.Send(rcvBuffer, 0, bytesRcvd, SocketFlags.None);
totalbytesEchoed += bytesRcvd;
}

extrem abschreckend.

Klar ist das kein Zuckerschlecken, aber du kannst auch nicht erwarten mit Integraltransformationen zu rechnen, bevor du nicht das Integrieren gelernt hast.

Aber ich kann mir einen Taschenrechner kaufen und mit diesem Integralrechnung machen und später die Integralrechnung erlernen, etwa weil man gerade kurz eine Fläche berechnen will und später darauf zurückkommt, wie das eigentlich funktioniert hat.

Wie ich bereits sagte, du kannst dir natürlich prinzipiell ein funktionierendes Programm zusammenstellen, doch das ist dann mehr Try-and-Error, eine Art Bastelstunde mit Code. Wenn du wirklich solide Programme schreiben möchtest musst du ganz unten beginnen und das braucht nunmal Zeit. Da mussten auch heutige Profis einmal durch.

Hmm, lustigerweise habe ich genau das Bastelstundengefühl, wenn ich vor so einen Tutorial-Monsterquelltext gesetzt werde und jetzt einfach mal ausprobieren muss, welche Zeilen denn jetzt das machen, was ich will und was ich für die minimale Funktion erstmal weglassen kann.
Allerdings habe ich mich vielleicht als etwas grundlagenfeindlich profiliert, das sollte eigentlich nicht so sein. Ganz im Gegenteil, auch mir ist klar dass die Grundlagen eigentlich die Basis zu erweitertem Wissen liegen und man das immer wieder brauch; wer die Grundlagen nicht kennt, kann kein vernünftiger Informatiker werden. Was ich nur bezweifle, ist, dass man zum Benutzen einer Komponente man wirklich vorher ihre gesamte Funktionsweise und alle Einzelteile ergründet haben muss. Ich glaube, wie schon geschrieben, der Ausgangspunkt ist besser die Komponente und man lernt nach und nach ihre Funktionsweise kennen, als dass man bei den Einzelteilen anfängt um dann an die Komponente zu gelangen. Bei der Erklärung des hardwaremäßigen Aufbaus eines PCs beginnt man doch auch nicht bei den einzelnen Chips in der CPU, sondern fängt erstmal damit an, wie ein Computer aussieht und was er macht. Dann kommen grob die Komponenten (CPU, Grafikkarte, RAM etc.), anschließend deren genauerer Aufbau. Einen PC benutzen kann man aber schon vorher.
Im übrigen habe ich auch erst vor sehr kurzem Verstanden, wo auf Speicherebene nun der genaue Unterschied zwischen Integer und String beispielsweise liegt - lustigerweise beim Backen eines Binärkuchens.

Wenn du Informatik studierst musst du auch die Grundlagen erlernen. So ist das nunmal.

Es ist nicht notwendig ASM zu kennen, um mit C# zu entwickeln. Aber du solltest mit der Syntax und den Sprachfeatures von C# vertraut sein und dazu gehören Exceptions. Es ist auch wichtig die Prinzipien der objektorientierten Programmierung zu begreifen, als auch den Vorgang, was bei der Kompilierung von C#-Code herauskommt.

Jap, wie gesagt, die Grundlagen sind wirklich extrem wichtig. Ich glaube nur eben nicht, dass man erst alle Grundlagen kennen muss, bevor man anfangen darf zu programmieren.

Bei der Netzwerkprogrammierung ist ein rudimentäres Wissen über das IP, TCP und UDP einfach unerlässlich.

Auf jeden Fall. Die grundlegenden Funktionsweisen der Protokolle kenne ich auch, genauso weiss ich, was Sockets sind und wie sie eigentlich funktionieren. Das Wissen ist jetzt leider eben nicht C#-spezifisch, deshalb wollte ich mal ganz den Grundcode, um zu verstehen wie eine Verbindung hier hergestellt wird und was ich dafür brauche. Was im Hintergrund da alles passiert, versuche ich natürlich auch noch zu verstehen.

Du kannst auch nicht am Ottomotor rumschrauben, wenn du nicht weißt, wie eine Zündkerze aussieht und wozu sie da ist.

Ich kann aber durchaus Starthilfe geben, tanken und den Motor starten und verwenden 😃 Tatsächlich muss ich erst wissen, wie eine Zündkerze aussieht, wenn ich da richtig dran rumbauen will - aber das ist doch kein Grund, nicht schon vorher Auto zu fahren, oder?

Mit 17 bist du noch jung, also keine Panik. Solltest du Informatik studieren, wirst du nach deinem Abschluss wissen was ich gemeint habe, als ich sagte das ohne die Grundlagen einfach kein guter Informatiker die Uni verlässt.

Ja, wie gesagt, Grundlagen sind sehr wichtig. Man hat einfach keine richtige Ahnung, wenn man nicht weiss, womit man überhaupt genau arbeitet. Aber man kann die Basics eben auch nach Verwendung noch lernen. Beispielsweise habe ich gelernt, dass man nachschauen kann, ob eine Zahl ungerade ist, indem man sie MOD 2 rechnet und dann eben eine 1 für true oder eine 0 für false herauskommt. Das war, bevor ich wusste, was MOD ist, trotzdem hats funktioniert. 😃

Es gibt mittlerweile einen ganzen Haufen selbsternannter Programmierer und Experten im Netz und im Reallife, die alleine nichts vernünftiges erarbeiten können, weil sie einfach keine echte Ahnung haben. Mir sind schon etliche begegnet. Ich kam auch ganz selten in den Genuß mit absoluten Spitzenleuten zusammenarbeiten zu dürfen, von denen man sehr viel lernen konnte.

Aber diese Experten sind rar und in der Industrie heiß begehrt

Naja, der Weg dahin ist hart und steinig, aber ich denke, er lohnt sich.
Auf jeden Fall kann ich jetzt gut weiterarbeiten und werde auch schon bald genauer die Funktionsweise des ganzen verstehen. Aber jetzt darf ich mich erst nochmal mit diesen total überflüssigen Listenklassen für Delphi vom Schulministerium befassen, für die Vorabiklausur am Dienstag...
Gruß
Tim

25.02.2010 - 18:45 Uhr

Oder muss ich etwa eine TCP-Client zu TCP-Client Verbindung machen, nur wie geht das dann?

Grundlagen lernen, dann klappts auch mit dem Verständnis. Es gibt keine "TCP-Client zu TCP-Client Verbindung".

Das war jetzt auch nicht so ernst gemeint, eher eine Suggestivfrage in Richtung "Oder hab ich alles falsch verstanden?" Aber ich habs jetzt geschafft, vielen Dank 😃

25.02.2010 - 18:36 Uhr

Ich glaube, heutzutage wird oft die Situation von Anfängern verkannt.
Für euch Profis gehört das meiste schon zum Selbstverständlichen und ihr könnt nur den Kopf schütteln, wenn eine total dumme Frage kommt.

Ich für meinen Teil bemerke zum Beispiel das Lehrsystem in Schulen - unsere gymnasialen Informatiklehrer sagen zu einem, wenn man den Bildschirmhintergrund ändert, "Du hackst hier die PCs, ich sag dem Direktor bescheid!". Das ist weder ein Witz noch eine Übertreibung, das hats bei uns gegeben.
Aus schulischer Perspektive lernt man leider anscheinend auch viele "Fachbegriffe" falsch. Mit optimiertem Code meinte ich vermutlich nicht dass, was ihr meint. In schulischer Ausbildung sind Exception-Handler nämlich schon optimierter Code. Exceptions sind einfach die Punkte, wo der Informatiklehrer sagt "Keine Ahnung warum dein Programm nicht läuft.". Und weggeht.

Jetzt ist natürlich klar: Wer nur über die Schule versucht, Programmieren zu lernen, ist völlig verloren. Das durchwühlen des Internets gehört dazu - meiner Meinung nach aber auch das Nachfragen in Foren bei Unverständniss. Das Problem hierbei: Wenn man in einem Turorial etwas nicht versteht, und deshalb nachfragt, wird man auf das Tutorial zurückverwiesen.
Zum Lernen suche ich meist erstmal die leichteste Methode, um das Problem zu lösen.
Die paar Zeilen, nach denen ich gesucht hatte, wären z.B. gewesen:


        static public void Starten()
        {
            ServerSocketC.Start();
        }

        static public void Verbinden(string IP)
        {
            ClientSocketC.Connect(IP, 8001);
            ClientSocketS = ServerSocketC.AcceptTcpClient();
        }

        static public string EmpfangeDaten()
        {
            StreamReader stream = new StreamReader(ClientSocketS.GetStream());
            return stream.ReadLine();
        }

        static public void SendeDaten(string command)
        {
            StreamWriter stream = new StreamWriter(ClientSocketC.GetStream());
            stream.WriteLine(command);
            stream.Flush();
        }

Bis ich die paar Zeilen aus den ganzen Tutorials und Forenbeiträgen rausgefischt habe, sind inzwischen bestimmt 2-3 Wochen vergangen - Zeit, die man, gerade beim Programmieren für die Schule, überhaupt nicht hat.
In besagtem Tutorial ist der ähnlichste Code, den ich finde:


using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
 
namespace CodePlanet.Articles.ProgrammingSockets
{
    /// <summary>
    /// Demonstration eines synchron agierenden TcpClienten.
    /// </summary>
    public class TCPClientClass
    {
        static void Main(string[] args)
        {
            if ((args.Length < 1) || (args.Length > 3)) {
                throw new ArgumentException("Parameters: <Word> [<Server>] [<Port>]");
            }
 
            byte[] byteBuffer = Encoding.ASCII.GetBytes(args[0]);
 
            // Verwende den angegebenen Host, ansonsten nimm den lokalen Host
            string server = (args.Length == 2) ? args[1].ToString() : Dns.GetHostName();
            // Verwende den angegebenen Port, ansonsten nimm den Standardwert 7
            int servPort = (args.Length == 3) ? Int32.Parse(args[2]) : 7;
 
            TcpClient client = null;
            NetworkStream netStream = null;
 
            try {
                // Erzeuge neuen Socket der an den Server und Port gebunden ist
                client = new TcpClient(server, servPort);
 
                Console.WriteLine("Connected to server... sending echo string");
 
                netStream = client.GetStream();
 
                // Sende den kodierten string an den Server
                netStream.Write(byteBuffer, 0, byteBuffer.Length);
 
                Console.WriteLine("Sent {0} bytes to server...", byteBuffer.Length);
 
                int totalBytesRcvd = 0;   // Anzahl der empfangenen Bytes
                int bytesRcvd = 0;        // Anzahl der empfangenen Bytes beim letzten
                // Aufruf von Read()
 
                // Denselben string wieder vom Server empfangen
                while (totalBytesRcvd < byteBuffer.Length) {
                    if ((bytesRcvd = netStream.Read(byteBuffer, totalBytesRcvd,
                            byteBuffer.Length - totalBytesRcvd)) == 0) {
                        Console.WriteLine("Connection closed prematurely.");
                        break;
                    }
                    totalBytesRcvd += bytesRcvd;
                }
 
                Console.WriteLine("Received {0} bytes from server: {1}", totalBytesRcvd,
                                  Encoding.ASCII.GetString(byteBuffer, 0, totalBytesRcvd));
 
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            } finally {
                netStream.Close();
                client.Close();
            }
        }
    }
}

Ihr könnt euch das wahrscheinlich garnicht mehr vorstellen, aber einem C#-Anfänger fallen da erstmal die Augen raus. Dann versucht er, irgendwie rauszufiltern welche Befehle jetzt eigentlich für das Senden und Empfangen an sich zuständig sind, immer wissend, dass man auf sich alleine gestellt ist, denn wenn man fragt wird man auf genau dieses Tutorial verwiesen. Häufig wird zwar nett angeboten, dass man für einzelne, unverständliche Zeilen nachfragen kann und das wird einem dann auch nett erklärt, aber als Anfänger sieht man sich leider meistens in der Lage, dass man die Augen schließen könnte und mit dem Finger auf irgendeine Zeile zeigt, und egal welche es ist, man versteht sie garantiert nicht. Der ganze Kram, der um die eigentlichen paar Zeilen steht, ist zwar meistens durchaus sinnvoll, aber er verwirrt. Ich für meinen Teil werde auch früh genug verstehen, dass es ständig zu Exceptions kommt und da mal ein paar Handler reinmüssen - das ist der Punkt, wo ich danach suche und lerne, das Tutorial jetzt vielleicht verstehe. Sowas kommt von alleine.

Zum Thema Grundlagenforschung:
Ich glaube, wenn man das so betreibt wie ihr empfehlt, kommen da so Leute wie Informatiklehrer raus. Wenn ich alles von Grund auf erschließen wollte, würde ich mit ASM anfangen, dann langsam zu C wechseln, vielleicht Cobald, Ruby und so einen Kram lernen, dann irgendwann mal Pascal, C++... Leider wäre ich dann aber schon so alt und es gäbe schon so viel Neues, dass ich nur noch Informatiklehrer werden könnte. Deshalb finde ich, ich kann durchaus erstmal den TCP-Client mit Listener probieren. Ist ja nicht gesagt, dass ich die grundlegenden Elemente nicht später auch erlerne, die genauen Methoden der C#-Sockets im Einzelnen (sowie ich auch inzwischen ein wenig ASM kann). Über Sockets im Allgemeinen war ich mir schon bewusst, leider nicht in C# - wie glaube ich schon erwähnt, war das in meiner ersten Programmiersprache "Delphi" alles um ein Vielfaches einfacher. In jedem Fall aber muss man glaube ich sich nicht von unten nach oben arbeiten - denn das dauert eine halbe Ewigkeit - sondern oben anfangen und bei Bedarf sein Wissen erweitern.

Im übrigen programmiere ich meist kein Chatprogramm um zu chatten, sondern eigentlich um die Komponenten kennenzulernen. Ich glaube auch, dass einem dein tolles Beispiel jetzt nicht alzu viel weiterhilft, wenn man andere Sachen programmieren will. Die Benutzung von TCP-Client und TCP-Listener aber schon.

Hier sind so ein paar Tutorials, die ich durchgeschaut habe. Eigentlich finde ich die auch ganz gut, aber...
http://www.codeplanet.eu/tutorials/csharp/6-csharp/4-tcp-ip-socket-programmierung-in-csharp.html
s.o.
TCP/IP Daten senden/empfangen
Einen Anfänger verwirrts zuerst mal, dass der Generated Code mit drin steht. Das ist aber eigentlich nicht weiter schlimm - aber das folgende Beispiel kann leider schon mehrere Clients über Hashtables behandeln und hat auch schon mehr als einen Thread. Wenn man nur als ersten Versuch mal einen String zum Localhost schicken will, ist man damit schon ziemlich überfordert.
[Tutorial] Client-/Server-Komponente über TCP-Sockets
Hier sind Verbindungsverwaltung und Multithreading leider auch schon eingebaut, bevor man überhaupt einen String verschicken kann. Da schmeisst man ganz schön schnell das Handtuch...
http://www.geekpedia.com/tutorial240_Csharp-Chat-Part-2---Building-the-Chat-Server.html
Deklaration von Events und Delegaten sind am Anfang auch nicht maximal einfach zu verstehen - in jedem Fall ist es nicht unbedingt leicht, das gesuchte herauszufiltern...
Dann gabs da noch eins, wo mit Interfaces gearbeitet wurde, den Link habe ich aber leider nicht mehr. Klar, steht auch alles im GuideToCSharp, aber in keinem Fall macht Programmierung sehr viel Spass, wenn man alles das schon können muss, bevor man die einfachsten Programme schreiben kann.

Ich kann schon verstehen, wie schwer es für manche Leute ist, sich vorzustellen man sei ein kenntnissloser Anfänger. Ich kann auch nicht verstehen, wie manche Leute sich nicht merken können, wie die Figuren beim Schach gehen können, und ich gehe auch oft an die Decke wenn ich irgendwem zum 10. Mal erklären muss, dass "=" kein Vergleichsoperator ist oder wie man einen Button auf eine Form kriegt. Oft sag ich dann auch verzweifelt nur noch: "Guck in die Hilfe..."
Leider vergesse ich dabei, wie viel einfacher es ist, wenn es einem erklärt wird - mir hat auch mal wer auf die Frage gesagt "Einfach da oben klicken und ins Fenster ziehen." Hätte ich mich da durch die Hilfe wühlen müssen, hätte ich wohl nie mehr als "Hello World!" zustande gebracht.

Ich glaube auch nicht, dass es unbedingt an meiner Intelligenz/Qualifikation liegt. Ich besuche das beste Gymnasium meiner Stadt, mache nächsten Monat das Abitur mit 17 Jahren, stand in Informatik immer auf der maximalen Punktzahl und mir wird dringend empfohlen, im Oktober mein Informatikstudium in Aachen aufzunehmen.
Damit will ich jetzt nicht etwa sagen, dass ich schon ein ziemlicher toller Typ bin, ganz im Gegenteil - ich weiss, dass ich nichts weiss, aber ich muss sagen, ich finds verhältnismäßig auch ziemlich schwer, vernünftig und methodisch dazuzulernen. Ich will auch nicht sagen, dass eure Hilfe generell irgendwie beschissen ist, aber durchaus zu mehr Nachsicht mit Anfängern aufrufen, da das hier nicht unbedingt das leichteste Fachgebiet ist - Leute, die vor 10 Jahren schon professionell angefangen haben, habens heute denke ich viel leichter als diejenigen, deren Zeit jetzt erst kommt und die sich mit den neueren Entwicklungen auseinandersetzen müssen, ohne die Älteren zu kennen - heute ein Anfänger zu sein, ist nicht mehr dasselbe, was es vor 10 Jahren war.
Oder mit anderen Worten: Die Neulinge von heute sind wahrscheinlich dööfer als ihr denkt.

Ich hoffe, ihr nehmt mit den Text nicht alzu übel und ich habe auch nicht den Anspruch, unbedingt im Recht zu sein, aber bisher sieht so meine Meinung aus.
Gruß
fortuneNext

PS: Poa, ich glaube jetzt habe ich das Topic ziemlich vergewaltigt. Entschuldigung an den Autor!

24.02.2010 - 16:30 Uhr

haha, ich hatte bloß aus irgendeinem Grund gedacht dass ich schon einen StreamReader im TCP-Client/Listener finde...
jetzt habe ich noch das Problem, dass der Listener garkeinen Stream hat? Zumindest gibts kein .getStream!

24.02.2010 - 00:28 Uhr

Hi,
ich hab mal ne Frage da ich genau das versuche aktuell zu bauen:
Ich will jetzt aus nem TCP-Listener eine ankommende Nahcricht lesen (das geht doch, oder?). Leider hat der keinen .getStream(). Wie dann?

Oder muss ich etwa eine TCP-Client zu TCP-Client Verbindung machen, nur wie geht das dann?

23.02.2010 - 00:41 Uhr

Hey, danke, das ist für mich schonmal hilfreicher als die ganzen Tutorials, in denen ich nur optimierten fertigen Code finden konnte.
Ich gehe davon aus, AcceptTcpClient() ist die richtige Methode, sie gibt als einzige einen TcpClient zurück.
Was ich persönlich auch noch nicht verstehe ist der genaue Unterschied bzw Vor-und Nachteile von asynchronen und nicht asynchronen Verbindungen. Gibt ja beim getStream Write/Read und BeginWrite/BeginRead/EndWrite/EndRead.
Und wo genau ich den StreamWriter/Reader finde habe ich auch noch nicht raus.
Ein 2-zeilen-Codebeispiel wäre super, nur die genaue Syntax fürs schreiben / lesen. 😃

Gruß
fortuneNext

22.02.2010 - 19:11 Uhr

Hm ich suche dasselbe, aber die Tutorials erscheinen wahnsinnig kompliziert... Ich habe auch schon mehrere gemacht, aber jedes sagt was anderes über die Funktionen die benutzt werden müssen... Listen, Accept, BeginListening, EndListening, Receive, Send, AcceptSocket, BeginReceive, EndReceive...
Irgendwie alles ein Riesenwust aus Funktionen. Es würde wirklich mal ein Tutorial helfen, indem man nur eine total primitive Verbindung sieht, ohne Exceptionhandler und son Kram, nur damit man erstmal die richtigen Funktionen kennenlernt. In Delphi damals brauchte ich für eine vom Autor angesprochene Verbindung bloß 4 Codezeilen. Hier versuche ich mich schon mehrere Wochen dran und muss mich inzwischen durch Multithreading und EventHandlern wühlen... Ich konnte noch nirgens einen wirklich ganz einfachen Chat für 2 Leute oder ähnliches entdecken, was einfach mal die Grundlegenden Befehle demonstriert...
Gruß

02.02.2010 - 15:20 Uhr

Ah super, habt mir geholfen 😄
Nun schafft ers nicht mehr. Sieg =)

Danke euch!

01.02.2010 - 12:20 Uhr

Hi,
ich habe ein Problem. Aktuell programmieren wir in der Schule in C# ein kleines Spiel. Jetzt haben wir eine Art Nerdkampf zwischen 2 Projektgruppen. Nun habe ich folgendes Problem:
Wir haben unsere XML-Charakterdaten mit RC4 verschlüsselt und senden auch so unsere Daten im Netzwerk. RC4 ist eigentlich nur ein Platzhalteralgorithmus für die Datei, aber das Problem wäre auch bei anderen das gleiche:
Und zwar hat es unser Gegner anscheinend geschafft, den Schlüssel aus dem zwischengespeicherten .net-Code mit einem zusätzlichen Programm auszulesen und die Daten so entschlüsseln zu können.
Jetzt die Frage:
Wie wehre ich mich gegen sowas? Wo kann ich einen Schlüssel vielleicht sinnvoll auslagern? Oder gibt es einfach Möglichkeiten, sich gegen ein direktes auslesen des .net-Codes zu wehren?
Danke für die Hilfe! =)

19.12.2009 - 14:23 Uhr

verwendetes Datenbanksystem: XML

Hi!

Die Codezeile

node.AppendChild(doc.CreateElement(Nodes[i].Connections[j].Name));
node.SelectSingleNode(Nodes[i].Connections[j].Name).Attributes.Append(doc.CreateAttribute("Power")).InnerText = Nodes[i].Connections[j].Power.ToString();

gibt bei mir immer die Exception "Der Ausdruck muss in einem Knotensatz resultieren." in der 2 Zeile zurück. Nodes_.Connections[j].Name ist ein String, Nodes_.Connections[j].Power ist ein Integer. Was habe ich falsch gemacht? Ich bin hiernach vorgegangen:
http://www.tsql.de/csharp/csharp_xml_erzeugen.htm

Nodes[] hat übrigens nichts mit den XML Nodes zu tun!

Danke 😃

04.09.2009 - 15:39 Uhr

Okay, JETZT hats geklickt. Super, vielen Dank =) Ich verwende nun ein Dataset in meiner Klasse, die nun static ist. 😄
Vielen Dank für die Hilfe und Geduld sag ich dann mal 😃

fortuneNext

03.09.2009 - 23:07 Uhr

Hmm, vielleicht seh ichs tatsächlich zu eng.
Ich hatte für Delphi immer im Kopf, auch aus dem Informatikunterricht (von dem ich nicht viel halte), dass die Form nur eine Schnittstelle zwischen User und Anwendung ist und steuernder Programmcode darin nichts verloren hat. Dazu zählten auch Klassen. Denn wenn ich das in der Klasse fest verankere, ist die Form ja elementar wichtig und kann nicht mehr jederzeit rausgenommen /ausgetauscht werden.
Ich hätte jetzt gedacht, das gehört zur OOP im Allgemeinen und ist in C# nicht anders 😕

Dass ich mich nicht von dem Konzept abwenden will, liegt daran, dass ich mir nicht ein Spiel überlegt habe und dann wie ich es gut umsetze, sondern zuerst das Konzept und dann nach was gesucht habe, was recht simpel ist und was sich darauf anwenden lässt. 😃
Nun gut, Singleton werde ich dann jetzt mal testweise versuchen zu implementieren.

Mein Fazit aus dem Topic wäre dann also, dass es nicht möglich ist, ein Objekt, ein Dataset oder irgendetwas anderes zu erstellen, ohne dass es irgendwann auf einem Grundtyp (Form, Konsole etc.) landet.
Ist das soweit richtig? =)

Ich danke schonmal für die viele Geduld mit mir 😄
fortuneNext

03.09.2009 - 21:57 Uhr

Also das mit den Datasets ist schon ein guter Hinweis =) Werde ich mal drüber nachdenken, so ein Dataset für den Speicher in der Klasse zu nutzen. Aber trotzdem muss ja die Gameklasse noch erstellen, oder, wenn ich das Dataset als gleichstufiger Speicher zur Gameklasse sehe, diesen auch irgendwo hinlegen.
Aber gibt keine Möglichkeit, das außerhalb der Form zu tun? Komme ich irgendwann zwangsläufig immer dazu, es auf die Form zu packen, egal, wie oft ich das nun einpacke?
In Delphi hätte ich ja einfach eine einzige Globale Variable vom Typ Game erstellt und darein dann alles andere gekapselt. Denn wie bereits angesprochen, gehört auf die Form ja eigentlich keine Logik/Programmsteuerung. Die insgesamte Steuerungsinstanz läge hier aber dann doch wieder auf der Form - diese soll ja aber eigentlich nur als reines Eingabeinstrument dienen.
Ist da keine Möglichkeit, das Objekt dort zu erstellen, wo auch die Form erstellt wird, sodass diese auf gleicher Ebene sind?

[Rechts unmöglich, nur links?]

03.09.2009 - 21:33 Uhr

Die Instanzen der Klasse sind in der Gameklasse. Anders gesagt, die Gameklasse ist einfach eine Art Container für alles Relevante.

Angenommen ich würde jetzt einen Kartenstapel als Klasse haben. Wohin mit diesem Objekt, wenn nicht auf die Form? Genauso, wo kommen die anderen Sachen hin? Gut, nun habe ich, wie gesagt, die Dinger dort hingeschrieben, wo sie am nähesten gebraucht werden - in der Gameklasse. Aber wohin nun mit der?

03.09.2009 - 20:53 Uhr

Die Objekte hab ich ja soweit sogar schon relativ fertig, alle in der Game-Klasse - mein einziges Problem soweit ist, dass ich immernoch nicht weiss, wie/wo ich jetzt optimalerweise ein Objekt davon erstelle, damit ichs auch nutzen kann ^^
Für die Anzeige haben wir auch schon eine Lösung gefunden, alles kein Problem 😃 Wie gesagt, das einzige Problem ist, dass ich es nicht schaffe, den Mechanics-Block (also das Game-Objekt) außerhalb des Input-Blockes (der Form) zu erstellen.

03.09.2009 - 20:35 Uhr

Das Teil ist ja im Prinzip Objektorientiert, oder? Es ist halt nicht alzu detailliert. Solche Fragen hab ich mir alle schon gestellt 😉 Die Regeln hab ihc mir selbst ausgedacht, es sind 2 Spieler, und Kartenstapel etc will ich ja auch alles machen, kommt alles in die Mechanics rein. Die Grafik zeigt wirklich nur den ganz äußeren Aufbau 😄
Dass die Funktionen noch zu Klassen gehören, und die Werte zu Klassen gehören, hab ich jetzt nicht rein getan, ich wollte eigentlich nur verdeutlichen, wo welcher Zugriff benötigt wird 😄

03.09.2009 - 18:51 Uhr

Aha, nun langsam beginne ich das Ganze langsam zu verstehen 😃

hast Du Dir schon, wie empfohlen, das Singleton-Muster angeschaut? Damit sollten einige Deiner Fragen beantwortet sein.

Angeschaut ja, allerdings blicke ich dank meiner mangelnden C#-Kenntnis noch nicht alzu gut durch, da ich noch nichtmal wirklich Syntax-sicher bin. Aber ich schaue es mir trotzdem genau an. Allerdings versuche ich trotzdem, das auch noch ohne das Muster hinzukriegen - sonst stoße ich beim nächsten Projekt wieder auf dasselbe Problem. 😃

Ansonsten - verwende den kleinsten Gültigkeitsbereich der Variablen, der möglich ist, sodass noch alle Teile Zugriff haben. Und wenn das die Klasse ist, dann ist das eben so. Wirklich "globale" Variablen gibt's ja sowieso nicht.

Jau, genau das habe ich vor. Mit den Grundregeln der OOP bin ich ja vertraut (aus Delphi) 😃
Aber einfach formuliert stehe ich ja vor der Problematik: Ich habe 2 verschiedene Dinge, die auf derselben Ebene stehen und beide dasselbe Objekt verwenden sollen. Aber: Eine Ebene höher kann ichs nicht deklarieren, denn dann wäre es global.

PS: Deine Anfängerfrage ist nicht blutig - auch wenn Du meinst es wäre eine Frage eines blutigen Anfängers...

Keine Sorge, das ist Absicht - Angewöhnung, ich hab den Fehler mal gemacht und formulier es seitdem immer so 😃

Da hast du dir deine Frage praktisch selbst beantwortet: Du darfst die Daten nicht lokal in einer Methode erzeugen, sondern z.B. als Feld bzw. Eigenschaft einer Klasse.

Genau das habe ich ja auch versucht - die ganzen Werte als Eigenschaften der Game-Klasse zu speichern. Aber nun kann ich ja schlecht die Game-Klasse in noch eine Klasse einbetten, und die widerrum in eine Weitere usw.

Genau! Die Speicherung von Daten hat in der GUI nach der 3-Schichten-Architektur absolut nichts verloren.

Eben. 😃
Das Problem ist eben, dass die Klasse die Steuerungsschicht ist, und nicht die Form, was aber bedeutet, dass das Objekt der Klasse nicht in der Form erstellt werden darf, sondern irgendwo anders!

An der Stelle musst du konkreter werden: Was soll da für wen zugänglich gespeichert werden? Dem "globalen Datenspeicher" stehe ich in der Form erstmal skeptisch gegenüber.

Hmm, ich hatte gehofft, das geht aus meinem ersten Post hervor. Es sind einfach die grundlegenden Spielelemente. Die "Lebenspunkte" der Spieler, ihre Karten usw. Sowas habe ich dann - wie im Code ganz oben - in die Klasse "Player" gekapselt, welche widerrum Bestandteil der Klasse "Game" ist. Game ist damit also die jenige Klasse, in der die Daten geschrieben werden, die später noch gebraucht werden*. Im ersten Moment muss sie erstmal für sich selber zur Verfügung stehen, damit sie mit den Daten aus sich selbst rechnen kann. Aber auch das Ausgabewerk muss (lesenden) Zugriff haben, um die Werte auf die Grafikebene zu projezieren, während das Eingabewerk auch eingegebene Spielbefehle an die Klasse weiterleiten muss. Hierzu würde ich gerne eine "Schnittstelle" in Form einer einzelnen Methode der Game-Klasse verwenden, in die sämtliche eingegebenen Daten eingespeist werden und die GameKlasse sie verarbeitet und entsprechend zuweist.

*Hier würde eine kleine Zwischenfrage mir schon helfen, die das Problem auf ein sehr elementares Niveau herabsenkt:
Wie schreibe ich ein Programm, in dem der User eine Zahl eingibt, und diese wird gespeichert und bei einem Buttonklick ausgegeben? Die Zahl soll dabei aber ausdrücklich nicht Form-gebunden gespeichert werden!

Nein. Sobald der Generator in diesem Beispiel von mehreren Methoden verwendet wird, macht es Sinn, ihn als privates Feld bzw. als private Eigenschaft der Klasse zu implementieren. Dass man ihn in diesem Fall statisch machen muss, liegt daran, dass aus einem statischen Kontext wie der Main-Methode nicht auf nicht-statische Elemente der Klasse zugegriffen werden kann.

Das klingt nach etwas sehr Nützlichem, vielleicht genau dem, was ich brauche. Leider kann ich mir noch nicht wirklich etwas Konkretes darunter vorstellen. Hätte vielleicht jemand ein ganz simples Codebeispiel für die Verwendung solcher statischen Sachen?

Das ist der knifflige Teil an der Architektur. Es soll ja nicht von jeder beliebigen Stelle aus auf die Daten lesend bzw. schreibend zugegriffen werden können.
So verlockend, wie das Singleton-Entwurfsmuster auch erscheint, birgt es auch einige (Design-)Gefahren und verleitet zu falscher Nutzung. Selbst die Entwickler des Patterns sehen dieses mittlerweile als zweischneidiges Schwert.

Richtig. Aber es soll sich auch nicht nur um eine lokale Sache handeln. Und wie oben erwähnt, müssen die anderen Teile trotzdem Zugriff erhalten.
Mit dem Singleton-Pattern beschäftige ich mich zwar, lasse es aber aus etwa diesen Gründen aus meiner Erstlösung erstmal heraus - vielleicht würden sich ja meine Probleme lösen, aber für die Erstlösung würde ich gern erstmal den "konventionellen" Weg erlenen.

@ Erfinder des Rates: Das Ding dient halt hauptsächlich zur Übung von C#. Ich will dabei lernen - deshalb versuch ichs, wie gesagt, nicht mit Alternativen, sondern den konventionellen Methoden. Trotzdem danke =)

@ herbivore: Hmm, in gewisser Weise brauchen die anderen schon Zugriff. Siehe vielleicht Skizze. 😃
Generell würde mir für das mit diesen statischen Objekten in der Klasse wirklich ein Codebeispiel helfen. Vond er Logik her verstehe ich das einigermaßen, aber wie das nun tatsächlich aussehen soll, weiss ich nicht wirklich.

Im Anhang hab ich mal die Anwendungsstruktur versucht zu skizzieren. Vielleicht hilft es ja ein bischen beim Verständnis 😃 Die farbigen Pfeile sind Eingabebeispiele.
Danke nochmal für die ganzen Mühen!

03.09.2009 - 00:20 Uhr

Hey, danke erstmal für die Antwort. Leider ist sie nur begrenzt hilfreich 😦

prinzipiell gilt, dass Variablen bzw. Objekte nur dort verfügbar sein sollen, wo sie gebraucht werden. Entsprechend sollten sie möglichst nah an ihrem "Einsatzort" erzeugt werden.
Globale Variablen sind kein guter Stil und sollten nach Möglichkeit vermieden werden.

Das entspricht ja etwa genau dem, was ich schon im ersten Post geschrieben habe.

Im Namespace geht nicht und wäre auch ohnehin als globale Variable ein unheimlich schlechter Stil

Dein Beispiel zeigt leider auch nur eine lokale Variable im Main(). Lokal ist aber für mich leider nicht möglich, zumindest nicht so - denn die Werte müssen ja beibehalten bleiben, um sie später wieder aufrufen zu können. Außerdem wird das Objekt nach Main() im Beispiel verworfen. Ich muss mit dem Objekt aber die gesamte Zeit über rechnen können. Auch eine Implementierung in die Form ist - wie gesagt - eher suboptimal, da ich eigentlich den Hauptprogrammcode nicht für die Form vorgesehen hatte. Mein Objekt soll eine Art globaler Datenspeicher für alle relevanten Daten sein - er muss sowohl für die Mechanics als auch für das Ein/Ausgabewerk verfügbar sein, da letztere das Objekt ja mit Daten speisen bzw. seine Daten interpretieren und ausgeben.

Würde eine andere Methode den Generator ebenfalls verwenden, könnte man diesen auch als statisches Feld der Klasse implementieren.

Um auf deine Frage zurückzukommen: static selbst hat mir globaler Verfügbarkeit nichts zu tun!

Dieser Teil klingt relativ nützlich. Leider verstehe ich ihn nicht. Den Generator als statisches Feld der Generatorklasse? Ist das nicht paradox?
Was genau hat es denn mit dem statisch auf sich? Es macht etwas klassenbezogen statt objektbezogen (zusammenfassung der Guides), wenn ich das richtig verstehe. Hierzu würde mir jedoch ein praktisches Beispiel denke ich besser veranschaulichen, wie das gemeint ist bzw. wie es sich anwenden lässt. Wie z.B. das nämlich dafür sorgen soll, dass in deinem Fall der Generator noch anderen Methoden zugänglich wäre, kann ich nicht sehen.

Im Endeffekt brauche ich auf jeden Fall einen Datenspeicher. Die Daten sind für alle Teile des Programms wichtig und dürfen eben nicht gelöscht werden. Als lokale Variable für die Form wäre ebenso schlecht wie eine globale Variable, da die Form in der Anwendung nicht der Hauptkontrollpunkt werden soll, sondern eben das Objekt. Außerdem könnte man dann eben nicht von anderen Klassen darauf zugreifen.

Danke für die Mühe, die ihr euch macht =)

fortuneNext

02.09.2009 - 23:03 Uhr

Hey,
vielen Dank für den Tipp mit den Singletons - werde ich mal in betracht ziehen. 😃

@ m0rius: In diese Guides habe ich ja - wie angemerkt - schon geschaut. Leider konnte ich dort keine Antwort finden. Wie ein Objekt erzeugt wird, ist mir ja klar - aber wo jetzt in meinem Anwendungsschema der richtige Ort ist, ist mir unklar. Und ich frage ja genau deshalb nach, weil ich aus den Openbooks eben nicht schlauer geworden bin. 😃
Danke trotzdem schonmal für die Hilfe =)
fortuneNext

02.09.2009 - 22:26 Uhr

Hallo,
ich und ein paar Freunde sind neu im C#. Vorher haben wir fast alle in Delphi programmiert. Nun wollen wir als unser erstes gemeinsames Projekt ein Minispiel bauen. Es ist keine von diesen riesigen Sachen, die sich die Leute immer am Anfang vorstellen, bis sie auf den Boden der Tatsachen geholt werden, sondern wirklich eine sehr sehr einfache Sache. Ich habe inzwischen schon einige Tutorials zu C# gelesen (z.B. den guidetocsharp), bin leider aber noch recht wenig zum praktischen OOP-coden gekommen.
Nun haben wir also dazu das "Programm" erstmal in 2 Namespaces geteilt - den Hauptnamespace "Output", der später die Übertragung der Daten an die Form steuern soll, und "Mechanics", wo das Spiel an sich abläuft.
Nun möchte ich also erstmal einen Platz für die ganzen verschiedenen Werte schaffen, die so im Laufe des Spiels abgespeichert werden müssen. Also habe ich im Namespace "Mechanics" die Klasse "Game" erstellt.

namespace Mechanics
{
    public class Game
    {
        class Player
        {
            int hitpoints
            {
            }
        }

        class Slot
        {
        }
    }
}

Nicht sonderlich komplex oder vollständig.

Hier die erste Zwischenfrage: Gibt es vielleicht in C-Sharp eine sauberere Möglichkeit für Klassen, die ohnehin nur 1x verwendet werden - so in Richtung einer Klasse, die von Anfang an als Objekt initialisiert ist, aber von der keine neuen Instanzen erzeugt werden können? (Hat das vielleicht was mit "Static" zu tun?)

Das Hauptproblem ist aber ein Anderes:
Bekanntlich muss ja nun ein Objekt dieser Klasse erzeugt werden. Nun frage ich mich: Wo zum Henker tue ich das?
Im Namespace geht nicht und wäre auch ohnehin als globale Variable ein unheimlich schlechter Stil. In die Klasse selber eine Instanz von ihr einzubauen scheint auch irgendwie paradox.
In die Form vielleicht? Einfach hineindefinieren?

Mechanics.Game Test1;
//oder
Mechanics.Game Test1 = new Mechanics.Game();

Hier wird der Name "Test1" in den FormMethoden nicht gefunden, wenn ich es mitten in die Formdefinition schreibe. Im form_Main(), also der Initialisierung, würde es ja nur lokal sein, das kann daher auch nicht die Lösung sein.
Allgemein wollten wir die Form allerdings nur als Eingabe nutzen, nicht als Steuerelement. Die Steuerung soll in den "Mechanics" liegen, das meiste davon in der Klasse "Game". Das "Game" also nur als lokale Variable in der Form zu deklarieren, erscheint also auch sehr suboptimal, schließlich soll das Game-Objekt in der ganzen Anwendung verfügbar sein, nach Möglichkeit dort auch im NameSpace "Mechancis".
Lange Rede, kurzer Sinn:
Wo lege ich das Objekt richtig an, sodass es überall verfügbar ist?

Danke schonmal =)
fortuneNext

21.07.2009 - 19:01 Uhr

Hmm k stimmt eigentlich =)
Nun gut, danke dir 😃

21.07.2009 - 18:27 Uhr

Hi nochmal 😃
Ich habe eine textbox erstellt, die, wenn der User etwas unerlaubtes eingibt, die BackColor Color.Red bekommt. Standartmäßig hat die Textbox die Standartfarbe "Window". Nun muss sich die Farbe auch wieder zurückstellen, doch ich finde bloß Color.White - woher krieg ich diese "Window"-Farbe? Nun könnte ich natürlich auch einfach stattdessen weiss nehmen, jedoch ist dann bei Programmstart (Txtbox.Backcolor == Color.White) == false . Ich könnte natürlich auch von Anfang an die Farbe auf White setzen, aber gibt es da eine bessere Möglichkeit als beim FormCreate jeden einzeln zu setzen? Direkt in den Eigenschaften ist White ja nicht als Auswahl. Die liebste Möglichkeit wäre mir aber wie gesagt, einen Vergleichswert für "Window" zu finden!

Danke 😃
fortuneNext

21.07.2009 - 17:37 Uhr

JAck30lena's Tipp hat hervorragend geklappt, vielen dank 😃

21.07.2009 - 16:59 Uhr

Nein nein, die SLN Datei hat ja den richtigen Namen! Es geht um den Unterordner, der im selben Ordner ist wie die SLN-Datei!

21.07.2009 - 16:22 Uhr

Hi,
ich habe von meinem Projekt jetz so ziemlich allem einen Namen gegeben, also den Namen des Projekts. Lediglich der Unterordner des Projekts, der also mit der .sln Datei in einem Ordner ist, heisst immernoch "WindowsFormsApplication2". Wenn ich ihn umbenne, ist die Projektdatei laut einer Fehlermeldung umbenannt oder verschoben worden und lässt sich nicht mehr öffnen. Wie benenne ich den Ordner korrekt um? Ich b enutze Visual Studio 2008.

07.07.2009 - 01:54 Uhr

Hey,
danke, das hat schonmal sehr geholfen 😃
Was ich mit den Bereichen meine, ist, dass ich z.B. alle ASCII-Zeichen von 25 bis 50 und von 75 bis 100 einschließe, ohne diese alle von Hand in ne Liste eintragen zu müssen 😃

07.07.2009 - 01:14 Uhr

Hallo, ich bin neu hier und generell in c#

Und zwar will ich immer den letzten Buchstaben einer Textbox mit anderen Vergleichen, die ich vorher definiere.

if (txtbox_binbits.Text[txtbox_binbits.Text.Length - 1] != 'a')
  1. Wie kann ich mehrere Sachen f+r das 'a' angeben, aber als endliche Liste? Also dass ich dorthin schreiben könnte 'a', 'b' o.ä?
  2. Wie kann ich das für einen unbegrenzt großen Zeichenbereich tun? Mit einem Intervall oder ähnlichem?
  3. Geht das auch noch mit den Zahlen in der ASCII-Zeichentabelle?
  4. Sind auch mehrere Bereiche möglich?

Danke 😃
fortuneNext