Forum: PC-Programmierung C# der gute Stil


von Dieter (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Dieter (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Arc N. (arc)


Lesenswert?

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...

von Karl H. (kbuchegg)


Lesenswert?

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.

von Dieter (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Bartli (Gast)


Lesenswert?

Is doch ganz einfach...Referenztypen werden by Reference übergeben, 
technisch bzw. spitzfindig gesehen werden die Referenzen selber aber 
natürlich by Value übergeben.

von Simon K. (simon) Benutzerseite


Lesenswert?

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 ;))

von Karl H. (kbuchegg)


Lesenswert?

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.

von Arc N. (arc)


Lesenswert?

> 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/

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Dieter (Gast)


Lesenswert?

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ß

von Karl H. (kbuchegg)


Lesenswert?

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.

von Arc N. (arc)


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Dieter (Gast)


Lesenswert?

@ 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#.

von Dieter (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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

von Dieter (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.