C# using-Anweisung

Stephan78

Ensign
Registriert
Sep. 2010
Beiträge
151
Hallo,

ich versuche in einer Funktion eine using-Anweisung zu implementieren,
scheitere aber daran, dass dann im Block das handle sr nicht mehr erkannt wird.
Wie mus das aussehen, damit es funktioniert?

Hier der Code:

Code:
try
				{
					// Sets the file the StreamReader will read from
					using (StreamReader sr = new System.IO.StreamReader(pfad));
					{
					string zeile;
					List<string> spalte = new List<string>();	
					
					// Read lines and fill array list. While loop will go through the whole file.
					while ((zeile = sr.ReadLine()) != null) 
					{
						// Splits the line at every comma. Places each split into the string array
						string[] lines = Regex.Split(zeile, trennzeichen);
						spalte.Add(lines[spaltenindex]);
					}
					anfwert=spalte[0];
					int i=spalte.Count;
					endwert=spalte[i-1];
					}
				}
 
Du darfst die Zeile nicht mit ";" abschließen...
 
Die Semikolons sind alle an den Stellen wo sie sein müssen. Probier mal using.Systems.IO.StreamReader sr =... oder so ähnlich. Ich weiß gerade nicht genau in welchem using die StreamReader Klasse liegt
 
Hey,

Ich würde den Strichpunkt am Ende dieser Zeile weglassen:

using (StreamReader sr = new System.IO.StreamReader(pfad));


;)
 
lord_naitch schrieb:
Die Semikolons sind alle an den Stellen wo sie sein müssen. Probier mal using.Systems.IO.StreamReader sr =... oder so ähnlich. Ich weiß gerade nicht genau in welchem using die StreamReader Klasse liegt

Ohweia, da muss sich aber jemand nochmal die Syntax von C# anschauen.
 
Man kann sich eigentlich merken: Wenn irgendwas mit Blöcken anfängt, kommen keine Semikolons hin. Oder wie könnte man das besser beschreiben? ...
Code:
for(;;) {}
while() {}
do {} while();
using() {}
if() {} else if() {} else {}
switch() {}
Gibt bestimmt noch mehr, welche mir gerade nicht einfallen und es werden sicherlich noch einige hinzukommen. ;)
 
Hi,

zu deinem Code:

Code:
            String path = "";
            String firstCell, lastCell;
            int column = 1;
            
            if (!File.Exists(path))
            {
                throw new FileNotFoundException("Please create the input file before using the application!");
            }
            using (StreamReader streamReader = new StreamReader(path))
            {
                String line;
                List<String> rows = new List<String>();
                while ((line = streamReader.ReadLine()) != null)
                {
                    String[] splittedLine = line.Split(',');
                    if (splittedLine.Count() >= column)
                    {
                        rows.Add(splittedLine.ElementAt(column));
                    }
                }
                firstCell = rows.FirstOrDefault();
                lastCell = rows.LastOrDefault();
            }

* Abkürzen von Variablen ist in Java vielleicht üblich, aber C# werden sie eher ausgeschrieben.
* Verwende gleich englische Variablennamen, das ist nämlich Industriestandard.
* Für das herausfinden der ersten und letzten Elemente kannst du Linq verwenden denn für genau solche Dinge wurde das entwickelt :-).
* try und catch sollte man nur in den verwenden wenn nicht anders möglich. Wenn ein File nicht gefunden wird solte hier auch die passende Exception geworfen werden und nicht einfach nichts passieren.
* Des weiteren ist es sehr hässlich im Code selbst Namespaces anzugeben! (Mit SHIFT+ALT+F10 kannst du sofern du gerade mit dem Mauszeiger in der Variable bist die usings automatisch hinzufügen und dann brauchst du die Namespaces nicht mehr anzugeben...)

mfg
aelo

edit:
wenn du möchtest kannst du auch das using-weglassen, dann musst du eben nach dem du mit dem lesen des File fertig bist die .Dispose()-Methode aufrufen. Denn etwas anderes macht das using auch nicht...
 
Aelo schrieb:
* Verwende gleich englische Variablennamen, das ist nämlich Industriestandard.

Wenn schon, dann aber richtig. Die Vergangenheit von "split" ist "split", nicht "splitted". ;)
 
sry, bist natürlich im Recht! :-)
 
Aelo schrieb:
H
Abkürzen von Variablen ist in Java vielleicht üblich, aber C# werden sie eher ausgeschrieben.

Da hast du vollkommen Recht. Das Abkürzen von Variablennamen ist eine Unart aus der alten C-Zeit und sollte immer vermieden werden, da sich unter sr niemand etwas vorstellen kann, erst recht nicht, wenn es mehr Variablennamen und Klassen sind.

* Verwende gleich englische Variablennamen, das ist nämlich Industriestandard.

Auch hier kann ich dir nur zustimmen. Das liegt aber weniger daran, dass es Industriestandard ist, sondern dass sich Variablen im Englischen einfach deutlich einfacher und direkter benennen lassen, als im Deutschen.

* Für das herausfinden der ersten und letzten Elemente kannst du Linq verwenden denn für genau solche Dinge wurde das entwickelt :-).

Linq benötigt .NET 3.5. Falls möglich sollte man sich auf die Features von .NET 2.0 beschränken, falls die Software nicht nur auf dem eigenen Entwicklungsrechner laufen soll. .NET 2.0 sollte auf 95% der Rechner schon oben sein und hier liefere ich meistens nicht einmal einen Installer mit dem Hauptprogramm mit. Bei .NET 3.5 ist das schon ziemlich eine Prozedur, Windows 2K Rechner werden grundsätzlich nicht unterstützt und es gibt auch gelegentlich Fälle, wo die Installation schief geht und man außer Systemwiederherstellung nur mehr den Rechner neu aufsetzen kann. Bei einem Kunden vielleicht noch auf dem Server sollte man sich gut überlegen, ob man den Schritt wirklich geht. Auch das schnelle Herunterladen von der Homepage ist dann vorbei, wenn man 200MB fürs .NET Framework braucht.

* try und catch sollte man nur in den verwenden wenn nicht anders möglich. Wenn ein File nicht gefunden wird solte hier auch die passende Exception geworfen werden und nicht einfach nichts passieren.

Grundsätzlich sollte man über jeden Event, der direkt vom GUI aufgerufen wird ein Try Catch haben, indem man grundsätzlich jede Exception fängt, diese anzeigt und in eine Logdatei (oder ähnliches) schreibt. Man kann nie alle Fehler einzeln bedenken und behandeln. Hier ist es besser alles pauschal zu behandeln (z.B. ein Fehler beim Laden führt zum Beenden des Programms, ein Fehler in einem Thread des Servers zum Schließen der Verbindung etc.) und nachher kann man bekannte Fehler immer noch getrennt behandeln.
Hier gilt es immer zwischen Benutzerfreundlichkeit und Wartbarkeit des Codes abzuwägen. Mehr abgefangene Fehler vergrößern den Code und machen ihn unübersichtlicher, bieten aber eventuell bessere Fehlertexte für Benutzer.
Es empfiehlt sich auch in erster Linie die direkte Fehlerursache Anzuzeigen und dann einen möglichen Behebungsvorschlag z.B. "Datei File01.xyz konnte nicht geöffnet werden. Bitte legen Sie die Datei an und stellen Sie sicher, dass der Benutzer darauf zugreifen kann:\n\n" + ex.toString()

Des weiteren ist es sehr hässlich im Code selbst Namespaces anzugeben! (Mit SHIFT+ALT+F10 kannst du sofern du gerade mit dem Mauszeiger in der Variable bist die usings automatisch hinzufügen und dann brauchst du die Namespaces nicht mehr anzugeben...)

Das ist zum größten Teil Geschmackssache. Ganze Namespaces sind unübersichtlich. Zu tief sollte man jedoch auch nicht gehen. Im Normalfall ist es am Besten bis zum letzten Namespace einzubinden (z.B. System.IO), jedoch keine Klassen (z.B. System.IO.StreamReader), weil es da oft zu Namenskonflikten kommen kann. Bei möglichen Namenskonflikten zweier Klassen nehme ich immer entweder nur den Klassennamen, oder den vollständigen Pfad (System.IO.StreamReader), aber nie eine Mischlösung (IO.StreamReader)

wenn du möchtest kannst du auch das using-weglassen, dann musst du eben nach dem du mit dem lesen des File fertig bist die .Dispose()-Methode aufrufen. Denn etwas anderes macht das using auch nicht...

Das using macht sowieso nur in einigen Fällen Sinn, da zusätzlich zum Aufrufen der Dispose Methode eventuell noch andere Aktionen gesetzt werden müssen. Falls eine Exception auftritt vertraue ich immer mehr auf die .Close Methode der jeweiligen Klasse (natürlich in einem weiteren Try Catch Block), als auf die .Dispose Methode. Gerade bei Softwarebibliotheken von Drittherstellern, würde ich nicht davon ausgehen, dass die ordentlich implementiert ist.

antred schrieb:
Wenn schon, dann aber richtig. Die Vergangenheit von "split" ist "split", nicht "splitted". ;)

SplitLine kann aber auch der Name für eine Funktion sein. Ich würde hier immer die gramatikalisch falsche, aber eindeutige Variante bevorzugen.
Ich hätte auch kein Problem eine deutschle Klasse Teebeutel in der Mehrzahl einfach stur Teebeutels zu benennen. Ein Variablenname soll die Bedeutung einer Variable möglichst eindeutig beschreiben, nicht mehr und nicht weniger.
 
andr_gin schrieb:
SplitLine kann aber auch der Name für eine Funktion sein. Ich würde hier immer die gramatikalisch falsche, aber eindeutige Variante bevorzugen.
Ich hätte auch kein Problem eine deutschle Klasse Teebeutel in der Mehrzahl einfach stur Teebeutels zu benennen. Ein Variablenname soll die Bedeutung einer Variable möglichst eindeutig beschreiben, nicht mehr und nicht weniger.

Also dem kann ich aber so 100%-ig gar nicht zustimmen. :freak: Wenn dir splitLine nicht eindeutig genug ist, dann wähle eben statt 'splitLine' 'tokenizedLine' oder einen anderen äquivalenten Bezeichner.
 
andr_gin schrieb:
Linq benötigt .NET 3.5. Falls möglich sollte man sich auf die Features von .NET 2.0 beschränken, falls die Software nicht nur auf dem eigenen Entwicklungsrechner laufen soll. .NET 2.0 sollte auf 95% der Rechner schon oben sein und hier liefere ich meistens nicht einmal einen Installer mit dem Hauptprogramm mit. Bei .NET 3.5 ist das schon ziemlich eine Prozedur, Windows 2K Rechner werden grundsätzlich nicht unterstützt und es gibt auch gelegentlich Fälle, wo die Installation schief geht und man außer Systemwiederherstellung nur mehr den Rechner neu aufsetzen kann. Bei einem Kunden vielleicht noch auf dem Server sollte man sich gut überlegen, ob man den Schritt wirklich geht. Auch das schnelle Herunterladen von der Homepage ist dann vorbei, wenn man 200MB fürs .NET Framework braucht.

Es sollte kein Problem sein diesen Installer im eigenen Installer (z.B. InstallShield) aufzurufen. Machen genügend andere Projekte auch. (Und das sind teils Projekte die extremere Qualitätsanforderungen haben als die worüber wir gerade diskutieren :-) )

Mit Windows 2000 hast du Recht, aber warum sollte ein aktuelles Projekt ein 11 Jahre altes Betriebssystem unterstützen?

Finde es schrecklich dass alte Software so lange unterstützt wird.
Siehe IE6: Der bereitet Webentwicklern immer noch Kopfzerbrechen. Wobei es für die meisten Probleme inzwischen Musterlösungen gibt.

Für kleinere Anwendungen hast du aber Recht, da ist es absolut kein Problem eine ältere .Net-Version zu verwenden.
Bei einer größeren empfiehlt es sich aber nicht wenn man dadurch zuviele Kompromisse eingehen muss. Hätte bei meinem letzten größeren .Net Projekt z.b. viel mehr Code schreiben müssen und die Performance wäre sicherlich auch um einiges schlechter gewesen wenn ich kein Linq verwendet hätte.

andr_gin schrieb:
Grundsätzlich sollte man über jeden Event, der direkt vom GUI aufgerufen wird ein Try Catch haben, indem man grundsätzlich jede Exception fängt, diese anzeigt und in eine Logdatei (oder ähnliches) schreibt. Man kann nie alle Fehler einzeln bedenken und behandeln. Hier ist es besser alles pauschal zu behandeln (z.B. ein Fehler beim Laden führt zum Beenden des Programms, ein Fehler in einem Thread des Servers zum Schließen der Verbindung etc.) und nachher kann man bekannte Fehler immer noch getrennt behandeln.
Hier gilt es immer zwischen Benutzerfreundlichkeit und Wartbarkeit des Codes abzuwägen. Mehr abgefangene Fehler vergrößern den Code und machen ihn unübersichtlicher, bieten aber eventuell bessere Fehlertexte für Benutzer.
Es empfiehlt sich auch in erster Linie die direkte Fehlerursache Anzuzeigen und dann einen möglichen Behebungsvorschlag z.B. "Datei File01.xyz konnte nicht geöffnet werden. Bitte legen Sie die Datei an und stellen Sie sicher, dass der Benutzer darauf zugreifen kann:\n\n" + ex.toString()

Da sind wir nun wohl geteilerter Meinung:
* Wenn wirklich bei jedem Event ein try/catch nötig wäre, wäre der Code sehr schlecht, denn so oft sollten Exceptions nicht geworfen werden.
* Es gibt in .Net einfache Möglichkeiten an einer zentralen Stelle (z.B. app.xaml.cs) alle Exceptions abzufangen die sonst nirgens behandelt werden, d.h. wenn gewünscht können sie dort dann in ein File oder eine DB geschrieben werden.

andr_gin schrieb:
Das ist zum größten Teil Geschmackssache. Ganze Namespaces sind unübersichtlich. Zu tief sollte man jedoch auch nicht gehen. Im Normalfall ist es am Besten bis zum letzten Namespace einzubinden (z.B. System.IO), jedoch keine Klassen (z.B. System.IO.StreamReader), weil es da oft zu Namenskonflikten kommen kann. Bei möglichen Namenskonflikten zweier Klassen nehme ich immer entweder nur den Klassennamen, oder den vollständigen Pfad (System.IO.StreamReader), aber nie eine Mischlösung (IO.StreamReader

Namespaces inklusive Klassennamen werden aber nur in Java verwendet. In C# gibt es dies zum Glück nicht.

andr_gin schrieb:
Das using macht sowieso nur in einigen Fällen Sinn, da zusätzlich zum Aufrufen der Dispose Methode eventuell noch andere Aktionen gesetzt werden müssen. Falls eine Exception auftritt vertraue ich immer mehr auf die .Close Methode der jeweiligen Klasse (natürlich in einem weiteren Try Catch Block), als auf die .Dispose Methode. Gerade bei Softwarebibliotheken von Drittherstellern, würde ich nicht davon ausgehen, dass die ordentlich implementiert ist.

Wenn IDisposable richtig implementiert ist sollten alle Resourcen freigegeben werden. Dafür wurde IDisposable geschaffen und der StreamReader ruft intern sicherlich auch nur die Close-Methode auf.

andr_gin schrieb:
SplitLine kann aber auch der Name für eine Funktion sein. Ich würde hier immer die gramatikalisch falsche, aber eindeutige Variante bevorzugen.
Ich hätte auch kein Problem eine deutschle Klasse Teebeutel in der Mehrzahl einfach stur Teebeutels zu benennen. Ein Variablenname soll die Bedeutung einer Variable möglichst eindeutig beschreiben, nicht mehr und nicht weniger.

Also ich bin mit tokenized zufrieden. :-) Guter Vorschlag!

@derlolomat:
Feedback ist wichtig! Und warum nicht gleich lernen wie man schönen Code schreibt :-)

mfg
aelo

edit:
Nochmals zum try/catch: Ich glaube hier haben wir andere Vorstellungen da ich von Desktopanwendungen ausgehe und du von Webapplikationen??
 
try durch File.Exists zu ersetzen ist grob fahrlässig, da braucht man gar nicht zu diskutieren.
 
carom schrieb:
try durch File.Exists zu ersetzen ist grob fahrlässig, da braucht man gar nicht zu diskutieren.

Warum?
Mir fallen nur fehlende Rechte ein, die sowieso nur bei Files die auch nicht geöffnet werden sollen, auftreten.
 
Nun, woher genau willst du wissen, ob die Datei beim Instanziieren des StreamReaders immer noch existiert?
 
Guter Einwand, aber da liegen nur wenige Taktzyklen dazwischen?
Irgendwann muss man auch abschätzen können wie wahrscheinlich Fehler ist.

Wegen Fehler die mit einer Wahrscheinlichkeit von 0.0000001% auftreten würde ich nicht den Code mit try{}catch{} verunstalten.
Meine persönliche Meinung und mit der bin ich eigentlich Recht gut gefahren beim letzten Projekt welches nun von 300 Personen täglich verwendet wird und über 20k-Codezeilen lang ist.

mfg
 
Wenn du damit gut schlafen kannst, dann sei das so. Aber bitte bringe so etwas nicht einem lernenden Anfänger bei.

Try/catch wurde genau für sowas erschaffen und ist bei FileIOs absolute Pflicht, egal ob man auf Dateiebene oder mit Netzwerkressourcen arbeitet. In diesem Fall zu sagen, dass man wegen der Lesbarkeit auf try/catch verzichten soll und lieber einen potentiellen Bug duldet, das hat mit Geschmackssache eigentlich nichts mehr zu tun, und dann ist es auch egal, ob der Bug jetzt in 1% oder 0,0001% der Fälle auftritt.

http://en.wikipedia.org/wiki/Defensive_programming


Mal anders gefragt: wenn du try/catch hier nicht verwenden willst wo es am essentiellsten ist, wo denn bitte dann?

edit: und ob try/catch wirklich unübersichtlich ist, darüber lässt sich streiten. Du hast eine if-Abfrage im Code die man nicht bräuchte, kann man auch so sehen..
 
Zuletzt bearbeitet:
Deine Erklärung klingt logisch :-).

Okay bei einem File-IO vielleicht echt keine schlechte Idee aber nicht bei jedem UI-Event wie weiter oben erwähnt :-)
 
Zurück
Oben