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
usingSystem;
2
usingSystem.Data;
3
4
namespacetest
5
{
6
classProgram
7
{
8
staticvoidMethod(DataTabledtIn)
9
{
10
DataColumndtTestCol=newDataColumn("dtTestCol");
11
12
dtIn.Columns.Add(dtTestCol);
13
}
14
15
staticvoidMain(string[]args)
16
{
17
DataTabledtTest=newDataTable();
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.)
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
DataTablea=newDataTable();
2
foo(a);
3
4
...
5
6
voidfoo(DataTablec)
7
{
8
....
9
}
ist also völlig gleichwertig zu C++
1
DataTable*a=newDataTable();
2
foo(a);
3
4
...
5
6
voidfoo(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).aspxhttp://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
voidMethod(refDataTabledtIn);
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ß.