Hallo, suche nach dem richtigen Programmierstil in der objektorientierten Programmierung mit C#. Ist das so ok, dass im Konstruktor von Form_Schnittstelle ein oCom Objekt der Klasse SerialPort erzeugt wird oder sollte sowas in einer Methode der Klasse Form_Schnittstelle gemacht werden? Also ich möchte in diesem Fenster Form_Schnittstelle einen Seriellen Comport mit entsprechender Baudrate und und ... öffnen. Nachdem die Einstellungen vorgenommen wurden, sollte das Windows Fenster wieder geschlossen werden können. Wenn das Fenster geschlossen wird, ist mein Objekt oCom noch da? Wenn ja, wann wird oCom gelöscht? Danke und Gruß namespace DeviceApplication2 { public partial class Form_Schnittstelle : Form { #region Eigenschaften, Felder, Objektdefinition SerialPort oCom; #endregion #region Konstruktor der abgeleiteten Klasse Form_Schnittstelle public Form_Schnittstelle() { InitializeComponent(); oCom = new SerialPort(); } #endregion
Dieter wrote: > Ist das so ok, dass im Konstruktor von Form_Schnittstelle ein oCom > Objekt der Klasse SerialPort erzeugt wird Kann man so machen > oder sollte sowas in einer > Methode der Klasse Form_Schnittstelle gemacht werden? Kann man ebenfalls machen > Nachdem die Einstellungen vorgenommen wurden, sollte das Windows Fenster > wieder geschlossen werden können. > > Wenn das Fenster geschlossen wird, ist mein Objekt oCom noch da? > Wenn ja, wann wird oCom gelöscht? Kommt drauf an. Gibt es danach das Form Objekt noch? Wenn nein, dann ist damit dann auch das oCom Objekt Freiwild (wenn es nicht auch noch von anderer Stelle her eine Referenz darauf gibt) und damit Kandidat beim nächsten GC Lauf aufgelöst zu werden. Wann das passiert weist du im voraus nicht. Wenn dein Kommunikationsobjekt also unabhängig von der Form existieren soll, dann ist wohl eine Mitgliedschaft im Form Objekt der falsche Weg. Der letzte Gedanke (dass das oCom Objekt besser nicht in die Form gehört) drängt sich sowieso auf, da eine serielle Schnittstelle nun mal eine beschränkte Resource ist (kann es nur einmal pro hardwaremässig vorhandener Schnittstelle geben) und wahrscheinlich eher eine 'Eigenschaft' des Programmes an sich ist als eine Eigenschaft einer Form. Ich würde einen Com Manager machen, der alle Com Objekte im Program verwaltet und diesen in die Mainform oder aber auch losgelöst davon machen. Wer eine Com Verbindung braucht, wendet sich an diesen Manager und fordert ein Com Objekt für die gewünschte SChnittstelle an. Der Manager regelt die Details und rückt das Objekt raus, sofern es verfügbar ist.
Habe noch ein(ig)e Frage(n). Mir ist soweit bekannt, dass man in C# auf Zeiger bewusst verzichtet hat. Sind scheinbar zu Fehleranfällig. In C ist das ja wohl unbestritten eine angenehme Sache. Angenommen ich möchte den Inhalt einer Datei in einen Buffer über eine Funktion einlesen. Eine andere Funktion soll auf den Buffer zugreifen und die Bufferinhalte bearbeiten. In C würde ich der bearbeitenden Funktion nen Zeiger auf den Buffer übergeben. Wie mache ich das in C#? Wird das Kind hier nur anders gerufen????? Anstelle Zeiger Referenz? Meines derzeitigen Wissens, können sich jegliche Objekte also auch Arrays nur in Klassen befinden. Wenn ich nun in einer Klasse ein Array erzeuge und eine Methode der selben Klasse befüllt mir dieses Array, so kann eine andere Methode der selben Klasse das Array wohl ohne Probleme bearbeitet. In C wäre dieses Aray modulglobal alle Funktionen in diesem Modul können auf dieses Array zugreifen. Soll in C eine Funktion aus einem anderen Modul (*.c file) auf dieses Array zugreifen, Muß ich dieser Funktion einen Zeiger auf das Array übergeben. Doch wie sieht es aus, wenn in C# eine Methode einer anderen Klasse auf dieses Array zugreifen soll? Also ich meine eine Methode der Klasse in der sich das Array befindet, ruft eine Methode in einer anderen Klasse auf und muß dann doch dieser Methode einen Zeiger oder eine Referenz auf das Array mitgeben. Wie wird das gemacht? in C: header einbinden funktion(*buffer) in C#: klasse.funktion(ref buffer) ?????? Danke und Gruß Dieter
Dieter wrote: > Mir ist soweit bekannt, dass man in C# auf Zeiger bewusst verzichtet > hat. Pst! Die heissen dort nur anders. > Sind scheinbar zu Fehleranfällig. > > In C ist das ja wohl unbestritten eine angenehme Sache. > > Angenommen ich möchte den Inhalt einer Datei in einen Buffer über eine > Funktion einlesen. Eine andere Funktion soll auf den Buffer zugreifen > und die Bufferinhalte bearbeiten. > > In C würde ich der bearbeitenden Funktion nen Zeiger auf den Buffer > übergeben. > > > Wie mache ich das in C#? Du übergibst das Objekt welches den Buffer rerpräsentiert an die Funktionen. > Wird das Kind hier nur anders gerufen????? > Anstelle Zeiger Referenz? Im Grunde: Ja. > Meines derzeitigen Wissens, können sich jegliche Objekte also auch > Arrays nur in Klassen befinden. Langsam. Nomeklatur. Eine 'Klasse' ist eine Beschreibung wie ein Objekt aussieht. Ein Objekt ist dann eine tatsächliche Instanzieerung einer Klasse. Eine Klasse ist also gewissermassen ein Bauplan. Und laut diesem Bauplan werden dann die Objekte zusammengebaut. > Wenn ich nun in einer Klasse ein Array erzeuge und eine Methode der > selben Klasse befüllt mir dieses Array, so kann eine andere Methode der > selben Klasse das Array wohl ohne Probleme bearbeitet. Ich denke du verstehst das richtig, auch wenn die Ausdrucksweise nicht ganz stimmt. > In C wäre dieses Aray modulglobal alle Funktionen in diesem Modul können > auf dieses Array zugreifen. So ungefähr kann man das vergleichen. Ja. > Soll in C eine Funktion aus einem anderen Modul (*.c file) auf dieses > Array zugreifen, Muß ich dieser Funktion einen Zeiger auf das Array > übergeben. Ja. Das hängt aber mehr damit zusammen, dass in C Arrays keine First-class-Objekte sind und als solche nicht übergeben werden können, wie das beispielsweise ein int oder ein double könnte. > > Doch wie sieht es aus, wenn in C# eine Methode einer anderen Klasse auf > dieses Array zugreifen soll? Sowas solltest du in OO strikt vermeiden. Eine Funktion die nicht zu einer Klasse gehört hat sich nicht direkt an einer Member-Variablen einer anderen Klasse zu vergreifen. Das ist gegen jedes OO-Prinzip. > Also ich meine eine Methode der Klasse in der sich das Array befindet, > ruft eine Methode in einer anderen Klasse auf und muß dann doch dieser > Methode einen Zeiger oder eine Referenz auf das Array mitgeben. > > Wie wird das gemacht? Du übergibst ganz eifnach das Array. Arrays sind in C# First Klass Objekte und können daher genauso als Parameter übergeben werden > > in C: header einbinden funktion(*buffer) > > in C#: klasse.funktion(ref buffer) ?????? Du brauchst kein ref. Übergib einfach nur das Array Objekt. In diesem Zusammenhang ist die Unterschiedung zwischen Value-Type und Reference-Type wichtig. Das solltest du nochmal in einem C# Buch deiner Wahl nachlesen.
Ich habe zu dem C# Gedönsel auch mal eine Frage. In der Schule arbeiten wir im Moment mit den ADO.NET Klassen und da bin ich irgendwie auf Ungereimheiten mit dem ref-Schlüsselwort gestoßen. Warum funktioniert folgendes
1 | using System; |
2 | using System.Data; |
3 | |
4 | namespace test |
5 | {
|
6 | class Program |
7 | {
|
8 | static void Method(DataTable dtIn) |
9 | {
|
10 | DataColumn dtTestCol = new DataColumn("dtTestCol"); |
11 | |
12 | dtIn.Columns.Add(dtTestCol); |
13 | }
|
14 | |
15 | static void Main(string[] args) |
16 | {
|
17 | DataTable dtTest = new DataTable(); |
18 | |
19 | Method(dtTest); |
20 | |
21 | Console.Write(dtTest.Columns[0]); |
22 | Console.Read(); |
23 | }
|
24 | }
|
25 | }
|
Ich kann es mir mit deiner Erklärung ehrlich gesagt nicht erklären. Wenn dtIn (Der Parameter von "Method") doch Call-By-Value ist, müsste an Method doch eine Kopie des Objekts dtTest(aus Main) übergeben werden. Wenn ich dort eine Spalte hinzufüge, dann dürfte das doch nur im lokalen Objekt der "Method"-Methode sein. Aber: Die erstellte Spalte ist auch in dtTest vorhanden. Oder ist es gar so, dass zwar die Klasse kopiert werden, aber die Columns-Collection der DataTable nur ein Pointer (Jaja, gibts nicht mehr..) auf einen Speicherbereich ist, der mitkopiert wird. Somit ist die Columns-Auflistung von dtIn (Parameter von "Method") an genau der gleichen Speicheradresse, wie dtTest (aus Main) und es funktioniert nur "zufälligerweise". Nun? Danke im Voraus! ;) PS: Ich bin der Meinung, dass hier das ref-Schlüsselwort notwendig ist.
Simon Küppers wrote: > Ich kann es mir mit deiner Erklärung ehrlich gesagt nicht erklären. Wie ich schon sagte: Entscheidend ist der Unterschied zwischen Value-type und Reference-type In a Nutshell: Value-type sind die eingebauten primitiven Datentypen wie int, double, char, etc. Alles andere ist Reference-type (mit Ausnahme von string, string wurde so programmiert, dass er sich wie ein Value-Type verhält) Warum ist das wichtig? Value-types werden (wie in C) per value übergeben; die Funktion kriegt eine Kopie Reference-types werden per Reference übergeben. > Wenn > dtIn (Der Parameter von "Method") doch Call-By-Value ist wird er nicht. DataTable ist ein Reference-type und wird per Reference übergeben. Die Unterscheidung ist u.A auch bei Zuweisungen wichtig: int i; int j = 5; i = j; // i wird der Wert in j zugewiesen, da Value Type DataTable a; DataTable b = new DataTable(); a = b; // a und b verweisen auf dasselbe Objekt, da Reference Type
Simon Küppers wrote: > Ich habe zu dem C# Gedönsel auch mal eine Frage. In der Schule arbeiten > wir im Moment mit den ADO.NET Klassen und da bin ich irgendwie auf > Ungereimheiten mit dem ref-Schlüsselwort gestoßen. > > Warum funktioniert folgendes > > Ich kann es mir mit deiner Erklärung ehrlich gesagt nicht erklären. Wenn > dtIn (Der Parameter von "Method") doch Call-By-Value ist, müsste an > Method doch eine Kopie des Objekts dtTest(aus Main) übergeben werden. > Wenn ich dort eine Spalte hinzufüge, dann dürfte das doch nur im lokalen > Objekt der "Method"-Methode sein. Aber: Die erstellte Spalte ist auch in > dtTest vorhanden. > > Oder ist es gar so, dass zwar die Klasse kopiert werden, aber die > Columns-Collection der DataTable nur ein Pointer (Jaja, gibts nicht > mehr..) auf einen Speicherbereich ist, der mitkopiert wird. Somit ist > die Columns-Auflistung von dtIn (Parameter von "Method") an genau der > gleichen Speicheradresse, wie dtTest (aus Main) und es funktioniert nur > "zufälligerweise". > Nun? > > Danke im Voraus! ;) > > PS: Ich bin der Meinung, dass hier das ref-Schlüsselwort notwendig ist. Die Erklärung war schon richtig. In C# sind, neben den Ganz- und Gleitkommazahlentypen, nur noch structs und enums Werttypen. Alles andere sind Referenztypen (bei Strings gibt's noch eine Einschränkung s.u.)
1 | void test() { |
2 | string s = "1234"; |
3 | change(ref s); |
4 | // ohne die refs ist s hier unverändert
|
5 | }
|
6 | |
7 | void change(ref string s) { |
8 | s = "abcd" + s; |
9 | s += "5678"; |
10 | }
|
Zu spät, dafür etwas ergänzt...
Man kanns auch so sehen: Wenn du in C# definierst DataTable a; dann definierst du in Wirklichkeit (in C++ Nomenklatur) kein DataTable Objekt sondern einen (reference counted) Pointer auf ein DataTable Objekt. Alles andere folgt dann daraus, zb. auch dass man in C# wesentlich öfter 'new' verwenden musst :-) DataTable a = new DataTable(); Wenn du daher a an eine Funktion übergibst, übergibst du in Wirklichkeit kein Objekt, sondern eben eine Kopie dieses Pointers (der aufgrund der Kopie logischerweise den Reference Counter des Objektes erhöht). C#
1 | DataTable a = new DataTable(); |
2 | foo( a ); |
3 | |
4 | ...
|
5 | |
6 | void foo( DataTable c ) |
7 | {
|
8 | ....
|
9 | }
|
ist also völlig gleichwertig zu C++
1 | DataTable* a = new DataTable(); |
2 | foo( a ); |
3 | |
4 | ...
|
5 | |
6 | void foo( DataTable* c ) |
7 | {
|
8 | c->IncrementReferenceCount(); |
9 | ....
|
10 | c->DecrementReferenceCount(); |
11 | }
|
wobei man in C++ natürlich sinnvollerweise einen reference counted Pointer aus der Boost Library nehmen wird, damit die Verwaltung der Reference Counter automatisiert wird. Lästerer könnten jetzt auch sagen, dass in C# die Übergabe eines Reference-Typen per Value gar nicht möglich ist und man daher gegenüber C++ eine Möglichkeit der Gestaltung des Programmes einbüsst. In der Praxis ist das aber nicht sooooo schlimm.
So, hab nun auch noch was. Für meinen PDA möchte ich ein Progrämmchen schreiben. Binn aber noch stark in der Lernphase und am Ausprobieren wie was geht. Das Programm auf dem PDA soll Daten über die Serielle Schnittstelle aufzeichnen. Das mit der Schnittstelle öffenen, Baudrate und Comport einstellen habe ich soweit hinbekommen. Nun möchte ich die empfangenen Zeichen in einer Datei abspeichern. Das gelingt mir auch. Doch möchte ich zu einem späteren Zeitpunkt selbige Datei erneut öffnen und Daten anhängen. Welche Klasse das unterstützt weiß ich nicht. Meine Methode die das ablegen der Daten realisiert, sieht -derzeit- so aus. Möchte also in einer anderen Methode den in "str_filename" enthaltenen Pfad erneut öffnen und Zeichen hinzufügen. public void Speicher_in() { // Objekt sfd_datei erzeugen sfd_datei = new SaveFileDialog(); sfd_datei.Filter = "txt files (*.txt)|*.txt"; sfd_datei.ShowDialog(); if (sfd_datei.FileName.Length > 0) { str_filename = sfd_datei.FileName; StreamWriter sw = new StreamWriter(str_filename); sw.WriteLine("Hallo"); sw.WriteLine("wie geht's"); //sw.Flush(); //sw.Close(); sw.WriteLine("gut"); sw.WriteLine("und selbst?"); sw.Flush(); sw.Close(); } } Danke und Gruß Dieter
Dieter wrote: > Nun möchte ich die empfangenen Zeichen in einer Datei abspeichern. > Das gelingt mir auch. Doch möchte ich zu einem späteren Zeitpunkt > selbige Datei erneut öffnen und Daten anhängen. Welche Klasse das > unterstützt weiß ich nicht. StreamWriter. Man Microsoft viel vorwerfen. Aber eines nicht: Die Doku zu C# ist mehr als ausführlich und auch leicht zu erreichen. Des weiteren gibt es in der MSDN Library auch noch jede Menge 'How To' Artikel. Und für die die die MSDN Lib nicht am Rechner haben, kann Help das ganze auch Online downloaden oder man liest das Help überhaupt online. http://msdn2.microsoft.com/en-us/library/336wast5(vs.90).aspx http://msdn2.microsoft.com/en-us/library/6ka1wd3w(VS.90).aspx
Is doch ganz einfach...Referenztypen werden by Reference übergeben, technisch bzw. spitzfindig gesehen werden die Referenzen selber aber natürlich by Value übergeben.
Karl heinz Buchegger wrote: > In a Nutshell: Value-type sind die eingebauten primitiven Datentypen > wie int, double, char, etc. > Alles andere ist Reference-type (mit Ausnahme von string, string wurde > so programmiert, dass er sich wie ein Value-Type verhält) Gut, habe ich mir fast schon gedacht. Ehrlich gesagt :-) > a = b; // a und b verweisen auf dasselbe Objekt, da Reference Type Ok, das ist somit auch klar. Karl heinz Buchegger wrote: > Man kanns auch so sehen: > > Wenn du in C# definierst > > DataTable a; > > dann definierst du in Wirklichkeit (in C++ Nomenklatur) kein > DataTable Objekt sondern einen (reference counted) Pointer > auf ein DataTable Objekt. Alles andere folgt dann daraus, zb. > auch dass man in C# wesentlich öfter 'new' verwenden musst :-) > > DataTable a = new DataTable(); Jup, versteh ich ;) > Lästerer könnten jetzt auch sagen, dass in C# die Übergabe eines > Reference-Typen per Value gar nicht möglich ist und man daher > gegenüber C++ eine Möglichkeit der Gestaltung des Programmes > einbüsst. In der Praxis ist das aber nicht sooooo schlimm. Ich finde es eigentlich nicht schlimm, "größere" Datentypen als Reference-Counted-Typ zu übergeben. Immerhin spart das Speicher (OkOk, nicht so das Argument) und ist während der Parameter-Übergabe möglicherweise noch schneller (Da kein Kopieren notwendig ist). Karl heinz Buchegger wrote: > Man Microsoft viel vorwerfen. Aber eines nicht: Die Doku zu C# > ist mehr als ausführlich und auch leicht zu erreichen. Des > weiteren gibt es in der MSDN Library auch noch jede Menge > 'How To' Artikel. Und für die die die MSDN Lib nicht am Rechner > haben, kann Help das ganze auch Online downloaden oder man > liest das Help überhaupt online. Absolut. Die Doku von den MFCs ist meiner Meinung auch auch ganz gut zu gebrauchen. Ich benutze in meinem Visual C# 2005 Express auch die eingebaute Online Hilfe, die aussieht, wie eine normale .chm Hilfe ;) Manchmal stört es mich aber schon, dass die MSDN etwas langsam ist, aber das ist wohl der Preis :-) PS:
1 | void Method(ref DataTable dtIn); |
Ist dann redundant. Richtig? DataTable würde durch "ref" ja zu einem Reference-Type - ist es aber schon -> Keine Auswirkung. PPS: Danke für diese Ausführlichsten Bemerkungen eurerseits! PPPS: Warum benutzt man in heutiger Zeit eigentlich so oft dynamische Speicherverwaltung? Klar, wenn man dynamisch veränderbaren speicher braucht (Also in der Größe dynamisch), dann ist das ein Muss. Aber wenn man schon den Speicherverbrauch und die Anzahl eines Objektes im Voraus (Während des Kompilierens) vorhersehen kann, braucht man sowas doch nicht zu machen! (Macht man in C ja schließlich auch nicht). Ist das nicht (theoretisch) viel langsamer dauernd vom Betriebssystem speicher zu holen? Außerdem wird dadurch ja schon der Speicher ganz schön fragmentiert, was wieder den Garbage Collector arbeiten lässt (Braucht auch wieder Rechenleistung). Oder ist es gar so, dass es dynamisch angeforderten Speicher schneller gibt? (Klingt vermutlich jetzt komisch, aber man weiß ja nie, was die Entwickler heutzutage wieder in Betriebssysteme einbauen ;))
Simon Küppers wrote: > PPPS: Warum benutzt man in heutiger Zeit eigentlich so oft dynamische > Speicherverwaltung? Ich würde mal sagen: Weil man in einer OO Sprache die entsprechenden Container fix fertig zur Verfügung hat. .... > Klar, wenn man dynamisch veränderbaren speicher > braucht (Also in der Größe dynamisch), dann ist das ein Muss. Aber wenn > man schon den Speicherverbrauch und die Anzahl eines Objektes im Voraus > (Während des Kompilierens) vorhersehen kann, braucht man sowas doch > nicht zu machen! Das kann aber oft zu einem Problem werden. +------------------------------------------------------------------+ | | | **** 1. Hauptsatz der Programmierung **** | | Alle Konstanten sind grundsätzlich als Variablen zu betrachten. | | | +------------------------------------------------------------------+ Was dir gestern noch von deinem Kunden zugesagt wurde (O-Ton: "Ne, ne das können Sie ruhig annehmen. Das wird nie größer") kann morgen schon höchst variabel sein (O-Ton: "Also das hätte ich schon gedacht, dass ist doch völlig klar, daß das mal so und mal so sein kann") Mit dynamischen Containern bist du auf jeden Fall auf der sicheren Seite. Wenn deine Annahme nicht stimmt, dann korrigiert der Container das ohne daß gleich die Laufzeit explodiert. Und das ist immer noch besser als ein Programmabsturz mit anschliessendem Datenverlust und wütenden Anrufen. > Ist das nicht (theoretisch) viel langsamer dauernd vom Betriebssystem > speicher zu holen? Man holt den ja nicht dauernd vom BS. Jedes ernstzunehmende Laufzeitsystem legt da eine Zwischenschicht ein, in der die grossen Speicherblöcke vom BS in kleinere Einheiten aufgebrochen und verwaltet werden.
> PPPS: Warum benutzt man in heutiger Zeit eigentlich so oft dynamische > Speicherverwaltung? Klar, wenn man dynamisch veränderbaren speicher > braucht (Also in der Größe dynamisch), dann ist das ein Muss. > Aber wenn > man schon den Speicherverbrauch und die Anzahl eines Objektes im Voraus > (Während des Kompilierens) vorhersehen kann, braucht man sowas doch > nicht zu machen! (Macht man in C ja schließlich auch nicht). Entweder aus Faulheit oder man plant und achtet darauf das spätere Änderungen möglichst einfach zu bewerkstelligen sind. Wenn man es unbedingt will (oder muss), kann man auch in C# statisch allozieren. Stichworte: unsafe, StructLayoutAttribute, LayoutKind, FieldOffset, ab C# 2.0 auch fixed etc. > Ist das nicht (theoretisch) viel langsamer dauernd vom Betriebssystem > speicher zu holen? Außerdem wird dadurch ja schon der Speicher ganz > schön fragmentiert, was wieder den Garbage Collector arbeiten lässt > (Braucht auch wieder Rechenleistung). Jein, normalerweise besorgen sich die Laufzeitumgebungen den Speicher in größeren Blöcken und benutzen dann einen eigenen (optimierten) Allokator. Der GC kann zwar defragmentieren, wenn er dazu gezwungen ist, braucht dann aber auch u.U. sehr lange für einen Durchlauf. Das Betriebssystem kann die MMU benutzen, um kontinuierliche Bereiche bereitzustellen > Oder ist es gar so, dass es dynamisch angeforderten Speicher schneller > gibt? (Klingt vermutlich jetzt komisch, aber man weiß ja nie, was die > Entwickler heutzutage wieder in Betriebssysteme einbauen ;)) Schnellere als in C/C++? Ja. Nur hat das nichts (bzw. wenig) mit dem BS zu tun. Siehe z.B. http://www.ibm.com/developerworks/library/j-jtp01274.html Schneller als statisch allozierter Speicher? Bei der Anforderung, nein. Beim Gebrauch u.U. schon, z.B. wenn Teile des vorab reservierten Speichers wegen Nichtbenutzung oder aus anderen Gründen auf die Festplatte ausgelagert wurden. p.s. eine schöne Spielwiese zum Testen war/ist die Einstiegsaufgabe des ICFP Contests 2006. http://www.boundvariable.org/
Karl heinz Buchegger wrote: > Was dir gestern noch von deinem Kunden zugesagt wurde (O-Ton: > "Ne, ne das können Sie ruhig annehmen. Das wird nie größer") > kann morgen schon höchst variabel sein (O-Ton: "Also das hätte > ich schon gedacht, dass ist doch völlig klar, daß das mal so und > mal so sein kann") > > Mit dynamischen Containern bist du auf jeden Fall auf der > sicheren Seite. Wenn deine Annahme nicht stimmt, dann korrigiert > der Container das ohne daß gleich die Laufzeit explodiert. > Und das ist immer noch besser als ein Programmabsturz mit > anschliessendem Datenverlust und wütenden Anrufen. Nagut. Ich hab gerade zwanghaft versucht ein Beispiel zu finden, wo das nicht zutrifft. Mir sind aber nur zB Schleifenvariablen eingefallen. Da würde es keinen Sinn machen, diese dynamisch zu allokieren - allerdings wird das ja bei C# auch überhaupt nicht gemacht. Folglich ist der Einwand von mir natürlich Käse. ;) >> Ist das nicht (theoretisch) viel langsamer dauernd vom Betriebssystem >> speicher zu holen? > > Man holt den ja nicht dauernd vom BS. Jedes ernstzunehmende > Laufzeitsystem legt da eine Zwischenschicht ein, in der die > grossen Speicherblöcke vom BS in kleinere Einheiten aufgebrochen > und verwaltet werden. Das ist mir schon klar. War vielleicht etwas übertrieben. Selbst das gute alte malloc() holt ja immer Blockweise Speicher. Aber wenn ich oft hintereinander für große Objekte Speicher allokiere und wieder freigebe, würde das sicherlich langsamer gehen. Wenn ich aber soweit bin, dass ich während der Laufzeit eine zur Kompilierzeit unbekannte Anzahl an Objekte erstelle, komm ich eh nicht mehr um dynamische Speicherverwaltung drumherum. Gut - hätten sich die Fragen auch erledigt. Es war nur so, dass sie mir schon Lange schwer auf der Seele lagen ;) Auf den ersten Blick sah das ganze nämlich erst relativ unsinnig aus, soviel Speicher dynamisch zu allokieren, aber wer von 8-Bit Mikrocontrollern mit <4kiB RAM kommt, der kennts nicht anders *g. (Gleiches gilt zum Beispiel für die Speicherverschwenderei bei PC-Programmierern... Grrr :-) Sowas gäbs auf nem kleinen Controller ja nie.) PS: Diese Reference-counted-Weise der Speicherverwaltung für Objekte wird eigentlich immer besser, je öfter man darüber nachdenkt. Man denke nur an die foreach-Schleife, die mit C# eingeführt wurde. Wenn ständig das aktuelle Objekt in die Schleifenvariable kopiert werden müsste, wäre das (je nach Objekt) ja unter Umständen sehr zeitaufwendig und langsam und würde unnötig Speicher verbrauchen.
Hallo, in meinem Progrämmchen möchte ich (der Anwender) eine einmalige Einstellung vornehmen, die irgendwo abgelegt und bei späteren Programmaufrufen dort abgerufen wird. Nun muß ich dazu sagen, das ich mehr aus der Microcontrollerecke komme und dort würde ich sowas in einem externen oder internen Eeprom oder Flashspeicher ablegen. Konkretes Beispiel: Die Einstellung der Seriellen Schnittstelle. In meinem Progrämmchen kann ich die Baudrate und den Com Kanal einstellen. Nun möchte ich das aber nur einmalig tun und dann sollten diese Einstellungen irgendwo nichtflüchtig abgelegt sein. Hier in Visual C# wüßte ich mir auch zu helfen, weiß aber nicht ob das so der mainstream ist. Also ich tät die Com Informationen in einem *.txt File auf CF, SD, oder dem Hauptspeicher meines PDAs ablegen. Der Ablafepfad und Dateiname muß da halt fest vorgegeben sein. In das File kann ich dann ja reinschauen und die dort abgelegten Einstellungen übernehmen. Ist das File nicht vorhanden oder leer, habe ich die Einstellungen noch nicht gesetzt. In diesem speziellen Fall, könnte ich die Com Settings wohl auch defaultmäßig im Programm hinterlegen. Möchte das aber nicht. Möchte gewisse einmal getroffene Settings in einem File abspeicher. Nu meine Frage. Macht man das so wie ich es oben angedeutet habe oder gibt es da elegantere Möglichkeiten. (config, ini, sys .....?????) Danke und Gruß
Ich würde im Web nach einer der dort unzählig vorhandenen Registry Klassen suchen und das damit machen. Oder aber die von C# zur Verfügung gestellte Klasse 'Registry', 'RegistryKey', etc einsetzen. Im Help findest du bei RegistryKey ein Beispiel wie man das macht. Der Trend bei Windows scheint allerdings wieder weg von der Registry und hin zu am Verzeichnis liegenden Configurationsdateien (ähnlich wie die Win 3.1 INI Files) zu gehen. Wobei dieser 'Trend' zu XML tendiert. Eine einfache Möglichkeit wäre daher zb eine DataTable einzusetzen, da diese sich selbst als XML lesen und schreiben kann (hab ich aber noch nie in der Form ausprobiert). PS: Du solltest dir Literatur zum Thema C# anschaffen. Das ist gut investiertes Geld.
> Ich würde im Web nach einer der dort unzählig > vorhandenen Registry Klassen suchen und das damit > machen. > Oder aber die von C# zur Verfügung gestellte Klasse > 'Registry', 'RegistryKey', etc einsetzen. > Im Help findest du bei RegistryKey ein Beispiel wie > man das macht. Nein, unter Projektmappe -> Projektname -> Eigenschaften -> Einstellungen gibt es eine deutlich einfachere Methode. Stichworte ApplicationSettings bzw. Anwendungseinstellungen, bei der die Einstellungen, auch von Steuerelementen, automatisch zugeordnet werden können (Steuerelement -> Eigenschaften -> ApplicationSettings -> PropertyBinding). Nur das Speichern muss man selbst erledigen (ala Settings.Default.Save()). Funktioniert zwar nicht bei allen Eigenschaften, aber für die meisten Fälle reicht's.
Arc Net wrote: > Nein, unter Projektmappe -> Projektname -> Eigenschaften -> > Einstellungen gibt es eine deutlich einfachere Methode. Stichworte > ApplicationSettings bzw. Anwendungseinstellungen, bei der die > Einstellungen, auch von Steuerelementen, automatisch zugeordnet werden > können (Steuerelement -> Eigenschaften -> ApplicationSettings -> > PropertyBinding). Nur das Speichern muss man selbst erledigen (ala > Settings.Default.Save()). Ah, ja. Danke für die Erinnerung. Bin halt ein alter VC++ MFC Programmierer. Da gabs dieses Zeugs alles noch nicht :-)
@ Karl heinz Buchegger habe bereits Go to C# Das C# Codebook Windows Forms Programmierung mit C# 2005 Windows Forms Programmierung mit C# .net wobei ich die beiden letzteren vermutlich bei ebay verscherbeln werde. Dann gibt es ja auch noch das Galileo Open Book C#. Aber wie (Sie oder Du) selbst aus Erfahrung weißt, findet man in der Einstiegsphase nicht immer gleich auf Anhieb das Passende oder Optimale. Da brauchts manchmal nur einen Wink in die richtige Richtung. Und dafür nochmals ein Danke an dieser Stelle. Beschäftige mich seit ca. 2 Wochen privat mit C#.
Hallo, Ggibt es in C# die Möglichkeit, an eine beliebige Stelle in ein Textfile zu schreiben? Ich kann derzeit ein *.txt erzeugen und Text darin ablegen. Mit using (StreamWriter sw = new StreamWriter("TestFile.txt")) { sw.Write("This is the "); } wird vom Anfang des Textfiles geschrieben. Mit using (StreamWriter sw = File.AppendText(path)) wird Text dem Textfile angehängt. Wenn ich nun ein Textfile mit 10 Zeilen habe und nur die Zeile 5 auslesen und je nach Inhalt überschreiben möchte, wie gehe ich da am besten vor? Momentan fällt mir dazu nur ein, den ganzen Inhalt des *.txt in einen String Buffer einzulesen, diesen zu bearbeiten und ihn dann in das *.txt zurückzuschreiben.
Dieter wrote: > Wenn ich nun ein Textfile mit 10 Zeilen habe und nur die Zeile 5 > auslesen und je nach Inhalt überschreiben möchte, wie gehe ich da am > besten vor? > > Momentan fällt mir dazu nur ein, den ganzen Inhalt des *.txt in einen > String Buffer einzulesen, diesen zu bearbeiten und ihn dann in das *.txt > zurückzuschreiben. Ist eine Möglichkeit. Bei grossen Dateien ev nicht mehr so toll. Ansonsten: Original File aus Temporäre Datei anlegen 4 mal Zeile aus Originalfile lesen Zeile in Temporärfile schreiben Zeile aus Originalfile lesen und mit der Änderung ersetzen manipulierte Zeile in Temporärfile schreiben while Zeile aus Originalfile konnte gelesen werden Zeile in Temporärfile schreiben beide Files schliessen Originalfile löschen Temporärfile umbenennen
Hallo, habe da einige Fragen zu dubiosen Objekten :o). Vorweg, da C# anfängt langsam Spaß zu machen, welche guten C# Bücher gibt es den so eurer Meinung nach? Also nun zu meinen derzeitigen Sorgen. Angenommen ich habe eine Klasse A mit öffentlichen Feldern und Methoden. Von dieser Klasse A erzeuge ich mir in einem anderen Klassenobjekt oB ein Objekt oA1 dieser Klasse A. Wenn ich nun in oB auf ein öffentliches Feld von oA1 schreibend zugreifen möchte, würde das ja so z.B. "oA1.feldname = 4 z.B." gehen. Wenn ich nun in oX ein weiteres Objekt z.B. oA2 der Klasse A erzeuge, und lesend "byte in = oA2.feldname z.B." zugreife, dann werde ich keine 4 auslesen denke ich. Im Objekt oX ist von dem Objekt oA1 ja nichts bekannt. Ich könnte in oX wohl auch ein oA1 erzeugen und dennoch habe ich mit diesem oA1 hier in oX keinen Zugang zu den Feldern des oA1 in oB weiter oben. Konkretes Beispiel: Über einen Comport der in oB geöffnet wird, fülle ich mir einen Buffer buffer1 in oA1. Der "Bauplan" ist in A hinterlegt. Beim anklicken eines Buttons soll in dessen Exception Handler, der sich ja in einem Form Objekt befindet, auf genau diesen buffer1 lesend zugegriffen werden. Nun muß ich mir in dem Form Objekt irgendwo ein Objekt der Klasse A erzeugen. Nur ist das Objekt ja nur eine Blaupause seiner Klasse. Wie komme ich also elegant an den Buffer Inhalt. Muß ich dafür den buffer1 in der Klasse (Bauplan) als static declarieren? Oder habe ich da was falsch verstanden? .....Gibt es andere Möglichkeiten? Danke und Gruß.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.