Laden...

Forenbeiträge von Red_Wraith Ingesamt 150 Beiträge

01.10.2010 - 17:53 Uhr

Ich habe eine Frage zu der Threadsicherheit der Ereignisse von System.Windows.Forms.Form, insbesondere von KeyPress und KeyUp.

Angenommen, die Methoden MainForm_KeyDown(...) und MainForm_KeyUp(...) greifen auf die gleichen Felder der Form zu. Kann es dann zu Threadsicherheitsproblemen kommen? Z.B. wenn ich zwei Tasten in kurzen Abständen drücke und zu ungleichen Zeiten wieder loslasse.

Beispielcode:


class MainForm : Form
{
    int x = 100;

    public MainForm()
    {
        this.KeyDown += new KeyEventHandler(MainForm_KeyDown);
        this.KeyUp += new KeyEventHandler(MainForm_KeyUp);
    }

    private void MainForm_KeyDown(Object sender, KeyEventArgs e)
    {
        this.x--;
    }

    private void MainForm_KeyUp(Object sender, KeyEventArgs e)
    {
        if (this.x >= 0)
        {
            // Kann es passieren, dass hier x < 0 ist?    
        }
    }
...
}

Ist in dem Beispielcode noch manuelle Synchronisierung (z.B. Locking) notwendig? Wenn nein, werden dann vielleicht sogar alle Events von Forms im gleichen Thread ausgeführt?

13.06.2008 - 17:34 Uhr

MCI ist ein guter Tipp, Danke.
Leider habe ich meine Sounddateien aber als eingebettete Ressource im Projekt und soweit ich sehe, kann man bei dem mci-String nur einen Dateipfad übergeben. Gibt es eine Möglichkeit mit dem MCI Sounddateien, die als eingebettete Ressource direkt in der Exe-Datei drin sind, abzuspielen? Und das OHNE den Stream temporär irgendwo als Datei abzuspeichern?

Beim SoundPlayer ging es:

SoundPlayer sp = new SoundPlayer(Projektname.Properties.Resources.Sound1);
13.06.2008 - 17:11 Uhr

Wenn man den send um ein notify erweitert

  
mciSendString(string.Format("play {0} from 0 notify",this._Alias),string.Empty ,0,this.Handle);  
  

dann kann man im Fenster ode Control welches this.Handle repräsentiert eine Benachrichtigung abfangen wenn der play fertig ist.

  
protected override void WndProc(ref Message m)  
{  
  base.WndProc (ref m);  
  if (m.Msg==MM_MCINOTIFY)  
  {  
  	//ich hatte hier ein Problem, dass er hier immer 2 mal reingelaufen ist   
  	//mit einem ganz kurzen Thread.Sleep trat es nimmer auf  
  	Thread.Sleep(1);  
  	//schliessen  
  	mciSendString(string.Format("close {0}",this._Alias),string.Empty ,0,this.Handle);  
  	//Play Complete  
  }  
}	  
}  
  

Gibt es eine Möglichkeit, festzustellen, wann eine Datei fertig abgespielt wurde, wenn man das ganze Soundmanagement mit MCI in einer statischen Klasse macht? Weil da habe ich ja kein Handle. Kann man vielleicht eines künstlich erzeugen?
Das Problem ist, dass der MCI keinen neuen Sound abspielt, bis man den alten gestoppt hat (auch wenn der schon ganz abgespielt wurde).

EDIT:
Ich habe eine Lösung gefunden: Ich setze einfach ein stop (über mciSendString) vor dem Abspielen (play), dann kann der gleiche Sound öfter abgespielt werden.
Aber ich wäre trotzdem für eine Antwort dankbar. Das obige könnte ich vielleicht an anderer Stelle noch gut gebrauchen.

13.06.2008 - 15:45 Uhr

Ich habe so meine Probleme mit der SoundPlayer-Klasse aus dem .NET2.0-Framework. Die SoundPlayer.Load()-Methode funktioniert nicht so wie erwartet, die SoundPlayer.Stop()-Methode benötigt viele Sicherheitsrechte und das schlimmste: Die Performance von SoundPlayer.Play() lässt zu wünschen übrig. Selbst das Abspielen von winzigen Wave-Dateien führt auf manchen Rechnern zu krassen Lags.

Gibt es eine gute und schnelle Alternative zur SoundPlayer-Klasse? Wenn nur WAV unterstützt wird, würde mir das reichen. Sollte WAV nicht unterstützt werden, könnte ich meine Sounddateien auch in andere Formate konvertieren.
Es würde mir sogar nur eine simple Lade-Funktion und simple Abspiel-Funktion reichen. Man müsste nicht mal die Abspielzeit oder die Lautstärke kontrollieren können.
Auf DirectX würde ich gerne verzichten, aber wenn es keine andere performante Möglichkeit gibt, muss ich wohl in diesen sauren Apfel beißen.

11.06.2008 - 22:00 Uhr

.NET 2.0

Die Methode SoundPlayer.Play() "lädt zunächst die WAV-Datei, sofern sie nicht bereits geladen ist, und gibt sie mithilfe eines neuen Threads wieder" (laut MSDN).
Um zu verhindern, dass es einen Lag gibt, wenn das erste Mal ein Sound abgespielt wird, habe ich schon bei Programmstart ein SoundPlayer.Load() verwendet. Leider ohne Wirkung. Der Sound wird immer noch erst geladen, wenn er das erste Mal abgespielt wird und deswegen gibt es einen unschönen Lag.

Mein Workaround: Nach dem SoundPlayer.Load() habe ich ein SoundPlayer.Stop() gesetzt. Damit wurde der Sound wunderbar schon bei Programmstart geladen, also vor dem ersten Abspielen.

ABER: Nun gibt es folgendes seltsames Problem: Das Programm startet nicht mehr von einem Netzlaufwerk (aber lokal schon noch!). Ohne Fehlermeldung geht das Programm einfach nach dem Starten wieder zu.
Dabei macht es keinen Unterschied, ob das Programm von einem echten Netzlaufwerk starte, oder von einem Netzlaufwerk, das nur auf die lokale Festplatte zeigt.
Wenn ich bei den Projekteigenschaften unter Sicherheit "Voll vertrauenswürdige Anwendung" aktiviere, dann bringt das leider auch nichts.
Wenn ich vor dem SoundPlayer.Stop() noch ein SoundPlayer.Play() setze, ändert das auch nichts daran, dass das Programm nicht mehr vom Netzlaufwerk startet.
Erst wenn ich das SoundPlayer.Stop() wieder herausnehme, dann startet das Programm wieder vom Netzlaufwerk, leider ist damit der Workaround von oben wieder zunichte gemacht.

Hier ein Teil des Codes von meinem Programm (wenn ihr noch andere Infos braucht, sagt es nur):


namespace SquareSmasher
{
    public enum SoundType { BallHardCollision, BallDeath, ItemDeath };

    static class SoundJukebox
    {
        private const int NumberOfSounds = 3;

        private static bool ready = false;

        private static Dictionary<SoundType, SoundPlayer> sounds = new Dictionary<SoundType, SoundPlayer>(NumberOfSounds);

        /// <summary>
        /// SoundJukebox initialisieren. Die einzelnen Sounddateien werden geladen. Diese Methode sollte beim Start des Programms aufgerufen
        /// werden, um zu verhindern, dass die Sounddateien erst beim ersten Aufruf von PlaySound geladen werden. Mehrmalige Aufrufe von
        /// Init() haben keine Wirkung.
        /// </summary>
        public static void Init() // geht nicht über einen statischen Konstruktor, weil der erst beim ersten Zugriff auf die Klasse aufgerufen wird
        {
            if (!ready)
            {
                sounds.Add(SoundType.BallHardCollision, new SoundPlayer(SquareSmasher.Properties.Resources.BallHardCollision));
                sounds[SoundType.BallHardCollision].Load(); // Sound laden; damit das Laden nicht erst beim ersten Play() vorgenommen wird
                sounds[SoundType.BallHardCollision].Play(); // trotz des Play()s läuft das Spiel nicht von Netzlaufwerken, wenn der Stop()-Befehl drin ist
                sounds[SoundType.BallHardCollision].Stop(); // ohne das Stop() gibt es seltsamerweise einen Lag beim ersten Abspielen des Sounds; evtl. funktioniert das Load() nicht richtig
                sounds.Add(SoundType.BallDeath, new SoundPlayer(SquareSmasher.Properties.Resources.BallDeath));
                sounds[SoundType.BallDeath].Load();
                sounds[SoundType.BallDeath].Play();
                sounds[SoundType.BallDeath].Stop();
                sounds.Add(SoundType.ItemDeath, new SoundPlayer(SquareSmasher.Properties.Resources.ItemDeath));
                sounds[SoundType.ItemDeath].Load();
                sounds[SoundType.ItemDeath].Play();
                sounds[SoundType.ItemDeath].Stop();
                ready = true;
            }
        }

        public static void PlaySound(SoundType st)
        {
            if (!ready)
            {
                Init();
            }
            sounds[st].Play();
        }
    }
}

Im Konstruktor der Haupt-Form wird aufgerufen:

SoundJukebox.Init();

NACHTRAG

Ich habe jetzt einmal das Projekt vom Netzlaufwerk aus im Visual Studio geöffnet und debuggt. Dann bekomme ich folgende Exception beim Aufruf der SoundPlayer.Stop()-Methode:

System.Security.SecurityException wurde nicht behandelt.
Message="Fehler bei der Anforderung des Berechtigungstyps System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089."
Source="System"
StackTrace:
bei System.Media.SoundPlayer.UnsafeNativeMethods.PlaySound(Byte[] soundName, IntPtr hmod, Int32 soundFlags)
bei System.Media.SoundPlayer.Stop()
bei SquareSmasher.SoundJukebox.Init()
bei SquareSmasher.MainForm..ctor(Size size)
bei SquareSmasher.Loader.Main(String[] args)

Kann vielleicht jemand damit etwas anfangen?

03.05.2008 - 22:19 Uhr

da scheinst du etwas falsch verstanden zu haben, da das "protected" aus Java dem "protected internal" aus C# entspricht und zwar stimmt es, dass es kein direktes Äquivalent zum "protected" aus C# gibt, aber das ist meiner Meinung nach auch nicht weiter wichtig, da ein "protected internal" auch seinen Zweck erfüllt.

Hm. Aber "protected internal" hat doch noch einen größeren Zugriffsradius als
"internal"? Laut Microsoft:

internal:
The type or member can be accessed by any code in the same assembly, but not from another assembly.

protected internal:
The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.

Wie kann dann "protected internal" seinen Zweck erfüllen? Wenn man verhindern will, dass Klassen, die nicht von einer bestimmte Klasse erben, auf diese zugreifen können.

Man sollte ja den Zugriffsradius so gut wie möglich einschränken, oder? Da finde ich die Java-Unterteilung "keine andere Klasse darf reinschauen" (private) und "alle anderen Klassen dürfen reinschauen (public, und in einer einzigen Assembly auch: protected) doch etwas arg grob.
Um auf meine anfängliche Frage zurück zu kommen: Steckt da irgendein tieferer Sinn dahinter, warum das bei Java so gemacht wurde? Irgendwelche OOP-Konzepte vielleicht?

17.04.2008 - 14:41 Uhr

Java hat ja kein richtiges "protected" wie C#, also ein Schlüsselwort, dass den Zugriff auf die eigene Klasse und die Unterklassen einschränkt. Ein "protected" in Java entspricht ja dem "internal" in C#.
Jedes Mal, wenn ich Java programmiere, nervt mich das, weil ich das "C#-protected" essenziell finde. Was haben sich die Entwickler von Java dabei gedacht? Wie soll man ein "C#-protected" in Java realisieren?

26.02.2008 - 11:40 Uhr

Okay, das würde wohl auch gehen. Aber ich habe mich jetzt für die eigene Klasse entschieden, damit, wenn zusätzliche Statusinformationen (neben dem bool) hinzukommen, nicht viel geändert werden muss.

22.02.2008 - 17:24 Uhr

Wenn sie allerdings private wären z.B. für IComparer also Klassen für Filterfunktionen besser gesagt allgemeine Hilfsklassen zur unterstützung der Hauptklasse die nur internen krimskrams abarbeiten, sehe ich da kein Problem.

Das sehe ich mittlerweile auch so. Private innere Klassen oder Strukturen können durchaus einmal praktisch sein, wenn man sie nur in einer bestimmten Klasse als Hilfsklasse bzw. Hilfsstruktur verwendet.
Aber unbedingt bräuchte man die inneren Klassen nicht.

22.02.2008 - 16:46 Uhr

Danke an alle, die mir geholfen haben.

Ich habe jetzt eine innere private Struct erstellt, die so ähnlich arbeitet wie KeyValuePair. Ich habe auf Properties verzichtet, weil diese Struct eh nur innerhalb der KlasseA verfügbar ist. Außerdem sehe ich eh keinen Sinn darin, bei Structs mit Properties zu arbeiten, weil Strukturen, die einer Methode übergeben werden, eh kopiert werden, sodass eine fehlerhafte Methode sowieso keinen Schaden anrichten kann (außer über die Referenz, aber das wäre bei einem Property dasselbe).

class KlasseA
{
    private struct ReferenceAndStatus
    {
        public KlasseB Reference;
        public bool Status;
        public ReferenceAndStatus(KlasseB reference, bool status)
        {
            this.Reference = reference;
            this.Status = status;
        }
    }

    //.........
}

PS:
Ich habe jetzt aus der struct eine class gemacht, weil ich sonst den Status nicht ändern kann, wenn die ReferenceStatus-Struktur in einer Liste liegt. Das Problem das ich meine war das gleiche wie das hier:
Der Rückgabewert "..." kann nicht geändert werden, da er keine Variable ist

22.02.2008 - 12:08 Uhr

Hm, ein KeyValuePair ist leider eine struct und wenn ich structs richtig verstehe, würde bei <KlasseA, bool> für jedes Element das ganze KlasseA-Objekt (+ ein bool) abgespeichert werden, nicht nur die Referenz + bool.

Du machst dir unbegründet Sorgen. KeyValuePair ist ne Struktur, das stimmt, aber das ändert doch nichts daran dass die Klasse nen Referenztyp ist und deshalb nur die Referenz darauf gespeichert wird.

Okay, dann sollte ich doch das KeyValuePair mal ausprobieren.

Nochmal zu meiner ursprünglichen Idee mit den zwei getrennten Listen:
Wird bei einem List.Add(..) das neue Element immer garantiert direkt hinter der letzten Stelle der Liste angehängt?
Wird bei einem Liste.Remove(..) immer das fragliche Element entfernt und die Elemente dahinter aufgerückt?
Diese Fragen spielen eine Rolle, weil sichergestellt werden muss, dass die Reihenfolge der Elemente in den beiden Listen immer übereinstimmt.

21.02.2008 - 23:21 Uhr

wie wäre es mit einem KeyValuePair<key, val> stat einer List<T>?

Hm, ein KeyValuePair ist leider eine struct und wenn ich structs richtig verstehe, würde bei <KlasseA, bool> für jedes Element das ganze KlasseA-Objekt (+ ein bool) abgespeichert werden, nicht nur die Referenz + bool. Bei umfangreichen Klassen könnte das schnell sehr viel Speicherplatz verbrauchen.

Oder funktionieren structs gar nicht so?

21.02.2008 - 23:02 Uhr

Ich hab eine lokale Liste aus Objekten:

List<KlasseA> dinge = new List<KlasseA>();

Jetzt würde ich gerne jedem Element dieser Liste eine Statusinformation in Form eines bools zuordnen, ohne diesen Wert in dem Objekt selbst abzuspeichern. Es gibt zu jedem Objekt genau eine Statusinformation. Wenn ein Objekt aus der Liste entfernt wird, dann soll auch seine zugehörige Statusinformation weg.

Ich habe mir schon überlegt, eine extra Klasse dafür zu erstellen, aber das erscheint mir wenig performant, außerdem würde ich diese Klasse dann nur für diesen Spezialfall brauchen:

class ReferenceAndBool
{
    KlasseA reference;
    bool flag;
    public ReferenceAndBool(KlasseA reference, bool flag)
    {
        this.reference = reference;
        this.flag = flag;
    }
}

Dann habe ich mir noch was überlegt:

List<bool> flags = new List<bool>();

Jedes Mal, wenn ein Eintrag in der Liste dinge gemacht wird (d.h. ein Add), dann auch einer in der Liste flags.
Beim Entfernen würde ich dann zuerst mit IndexOf die Position des aus dinge zu entfernenden Elements bestimmen, dann dieses entfernen (mit Remove) und schließlich mit RemoveAt den Eintrag in flags an dieser Position entfernen.
Ist so sichergestellt, dass die Zuordnung immer stimmt, also die Indizes zusammenpassen? Oder könnten durch das Löschen z.B. Lücken entstehen, die dann wieder aufgefüllt werden, oder hintere Elemente zwar z.B. bei dinge nach vorne geschoben werden, bei flags aber nicht?
Auch wenn es da keine Probleme geben würde, ist es nicht so toll, dass Informationen die eigentlich zusammengehören, getrennt sind.

Gibt es eine elegante Lösung?

21.02.2008 - 22:12 Uhr

Was ist der Sinn von inneren Klassen in C#?
In Java braucht man sie z.B. um Listener richtig benutzen zu können, weil es keine Events gibt. Aber in C# habe ich sie bisher noch nie gebraucht.

Kann mir jemand ein praktisches Beispiel geben, wo innere Klassen sinnvoll oder sogar notwendig sind?

15.10.2007 - 19:21 Uhr

Vielen Dank. Es hat wunderbar geklappt. Jetzt lässt sich der "Schläger" ohne Verzögerung steuern.

15.10.2007 - 16:05 Uhr

Original von herbivore
starte bei KeyDown einen eigenen Timer, den du bei KeyUp wieder stoppst. Behandle die Move-Operationen in Timer.Tick und nicht in KeyDown.

Ich habe mich mal auf die linke Pfeiltaste beschränkt und da funktioniert das schon ganz gut. 🙂

Muss ich für jede Taste, die zum Steuern benutzt wird, eine eigene "Ticker"-Methode schreiben, die vom Tick-Event ausgelöst wird? Oder kann ich auch irgendwie die jeweils gedrückte Taste an eine einzige Methode übergeben, und dort in Abhängigkeit der Taste entscheiden, wie sich der "Schläger" bewegt? Oder bleibt mir nichts anderes übrig, als die gerade gedrückte Taste als Attribut abzuspeichern?

15.10.2007 - 15:19 Uhr

Okay, alles klar. Danke, Herbivore.

15.10.2007 - 00:32 Uhr

Original von tscherno

  
int Test1 = Convert.ToInt32(Math.Floor(Test)) ;  
  

Gibt es eigentlich einen Unterschied zwischen den möglichen Ergebnissen bei

int Test1 = Convert.ToInt32(Math.Floor(Test));

und

int Test1 = (int) Math.Floor(Test);

und

int Test1 = (int) Test;

wenn Test ein float ist (oder ein double)?

14.10.2007 - 22:18 Uhr

Gibt es eine Möglichkeit die Verzögerung der Tastatur unter Windows zu ignorieren, die jeder Nutzer in Systemsteuerung/Tastatur einstellen kann?

Der Hintergrund: Ich schreibe einen kleines Breakout-Spiel und die Verzögerung wirkt sich sehr stark auf die Steuerung des "Schlägers" aus.

Ich nutze in der Hauptform den folgenden Code für die Tastatursteuerung (ich habe unwesentliche Sachen mit "..." abgekürzt):

this.KeyDown += new KeyEventHandler(OnKeyDown);

und

private void OnKeyDown(Object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Left:
...
            this.playerBat.MoveLeft( ... );
...
            break;
...
14.10.2007 - 17:46 Uhr

Okay, jetzt ist alles klar. Vielen Dank.

12.10.2007 - 18:17 Uhr

Ich war der Meinung, die Vererbung vollständig verstanden zu haben. Es scheint aber nicht so zu sein. Beim folgenden Code bekomme ich zwei Fehler:

class BasisKlasse
{
    private int wert;
    private void Methode()
    {
    }
}

class Ableitung : BasisKlasse
{
    private void Test()
    {
        this.wert = 5;
        this.Methode();
    }
}

Fehlermeldungen:
Der Zugriff auf "BasisKlasse.wert" ist aufgrund der Sicherheitsebene nicht möglich.
Der Zugriff auf "BasisKlasse.Methode()" ist aufgrund der Sicherheitsebene nicht möglich.

Ich war immer der Meinung, dass eine abgeleitete Klasse durch die Vererbung alle Attribute und Methoden der Basisklasse bekommt. Deswegen sollte meiner Meinung nach der Zugriff auf die eigenen Attribute mit this möglich sein (ich habe ja nicht base geschrieben).

Wie lässt sich das erklären? Kann es vielleicht sein, dass sich hier C# von Java unterscheidet? Oder würde der Code in Java auch zu einem Fehler führen?

03.09.2007 - 22:29 Uhr

Ich habe jetzt die Lösung gefunden. Es lag an der Reihenfolge. Scheinbar muss man den Writer vor den Readern schließen. Warum das so ist, kann ich mir aber nicht erklären, vor allem nicht, warum das auch anders funktioniert hat, bevor ich IDisposable implementiert habe.


protected virtual void Dispose(bool fDisposing) {
	if (fDisposing) {
		sw.Close();
		br.Close();
		sr.Close();
		//fs.Close(); // unnötig, da der Stream bereits bei sw, sr und br geschlossen wird
	}
	// Hier die unverwalteten Ressourcen freigeben (gibts keine?)
}

Danke an alle, die mir bisher in diesem Thread geholfen haben.

Zum Verständnis (bzw. zu dem was ich nicht verstehe):

Was ich bisher verstanden habe, ist warum man überhaupt Close() aufruft: Um die Garbage Collection sofort zum Aufräumen des jeweiligen Streams zu zwingen, weil solche Objekte wie Streams schnell viel Speicher belegen (bis die Müllabfuhr irgendwann kommt).
Was ich jedoch nicht verstehe, ist folgendes: Warum ruft der Destruktor ~Xyz(), der ja von der Garbage-Collection aufgerufen wird, wenn auf ein Xyz-Objekt keine Referenz mehr existiert, die Close()-Methoden der einzelnen Streamreader/-Writer nicht auf? Wenn das Xyz-Objekt nicht mehr benötigt wird, dann können doch auch seine Member verschwinden, oder?

Ich muss auch zugeben, dass ich nicht recht den Unterschied zwischen "von der Garbage Collection entsorgt" und "die Close()-Methode des Objekts wurde aufgerufen" verstehe.

Es wäre schön, wenn mir das jemand erklären könnte.

03.09.2007 - 20:30 Uhr

Das habe ich jetzt ausprobiert:


protected virtual void Dispose(bool fDisposing) {
	if (fDisposing) {
		sr.Close();
		if (sw != null) {
			sw.Close();
		}
		if (br != null) {
			br.Close();
		}
		//fs.Close(); // unnötig, da der Stream bereits bei sw, sr und br geschlossen wird
	}
	// Hier die unverwalteten Ressourcen freigeben (gibts keine?)
}

Aber ich bekomme beim sw immer noch:
System.ObjectDisposedException wurde nicht behandelt. Message="Auf eine geschlossene Datei kann nicht zugegriffen werden."

Nach dem sr.Close() ist weder sr, noch sw, noch br null. Wenn ich statt "sw != null" schreibe: "sw.BaseStream != null" hilft dies leider auch nicht.

PS: Ich verstehe auch nicht, warum man überhaupt einen Destruktor braucht, und ob Streams nun "unverwaltete Ressourcen" sind, oder nicht.

03.09.2007 - 19:50 Uhr

Original von herbivore
hm, komisch. Dispose (oder hier Close, was ja auf gleich kommt) darf man eigentlich beliebig oft aufrufen.

Hm, hat vielleicht sonst jemand eine Idee, wo das Problem begraben ist?

25.06.2007 - 21:37 Uhr

Danke für die Hinweise.
Ich habe IDisposable implementiert und meine Close()-Funktion nach Dispose() umbenannt. Dann bekomme ich aber eine ObjectDisposedException beim sw.Close();. Ich verstehe das nicht. Im Endeffekt müsste es doch genauso funktionieren, wie zuvor?

Jetzt habe ich versucht, analog zu dem Codesnippet vorzugehen, bekomme aber den selben Fehler. Was muss ich ändern, damit es funktioniert? Ich glaube ich verstehe das alles nicht so richtig.


class Xyz : IDisposable {
	private FileStream fs;
	private StreamReader sr;
	private StreamWriter sw;
	private BinaryReader br;

	public Xyz(String path) {
		fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
		sr = new StreamReader(fs, Encoding.Default);
		sw = new StreamWriter(fs, Encoding.Default);
		br = new BinaryReader(fs, Encoding.Default);
	}	

	public void Close() {
		((IDisposable)this).Dispose();
	}

	void IDisposable.Dispose() {
		Dispose(true);
		GC.SuppressFinalize(this);
	}

	~Xyz() {
		Dispose(false);
	}

	protected virtual void Dispose(bool fDisposing) {
		if (fDisposing) {
			sr.Close();
			sw.Close();
			br.Close();
			//fs.Close(); // unnötig, da der Stream bereits bei sw, sr und br geschlossen wird
		}
		// Hier die unverwalteten Ressourcen freigeben (gibts keine?)
	}
}

25.06.2007 - 20:11 Uhr

Okay, jetzt ist alles klar. Dankeschön. Meine Close()-Methode sieht jetzt so aus:


public void Close() {
	sw.Close();
	sr.Close();
	br.Close();
	// fs wird automatisch durch die anderen Closes geschlossen
}

25.06.2007 - 19:30 Uhr

Schon mal Danke für die Antwort.

Bei den Close-Methoden der Writer/Reader heißt es, wenn ich mit der Maus darüber fahre im VS 2005: "Schließt das aktuelle StreamxxxObjekt und den zugrunde liegenden Stream".
Bei den Dispose-Methoden der Writer/Reader steht: "Gibt alle vom Objekt verwendete Ressourcen frei".
Das macht bei mir den Eindruck, dass bei den Close-Methoden der Writer/Reader der Stream auch geschlossen wird, bei den Dispose-Methoden jedoch nicht.
Wäre es dann nicht sinnvoller bei den Writern/Readern die Dispose-Methoden zu verwenden und beim FileStream die Close-Methode, damit nicht unnötigerweise der Aufruf zum Schließen des Streams gestartet wird?
Die Kurzbeschreibung von Close() bei FileStream erweckt auch den Eindruck, dass dort mehr passiert als bei Dispose().

Oder ist Close und Dispose sicher tatsächlich identisch?

25.06.2007 - 19:05 Uhr

Ich habe folgendes Szenario: Ein StreamReader, ein StreamWriter und ein BinaryReader benutzen den gleichen FileStream. Jetzt würde ich meine Close()-Methode gerne optimieren, da ich vermute, dass ein Teil ihrer Befehle unnötig ist. Die Angaben in der MSDN sind recht schwammig, deswegen frage ich hier. Hier ist der Code:


class Xyz {
	private FileStream fs;
	private StreamReader sr;
	private StreamWriter sw;
	private BinaryReader br;

	public Xyz(String path) {
		fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
		sr = new StreamReader(fs, Encoding.Default);
		sw = new StreamWriter(fs, Encoding.Default);
		br = new BinaryReader(fs, Encoding.Default);
	}

	public void Close() {
		sw.Dispose();
		sr.Dispose();
		fs.Dispose();
		sw.Close();
		sr.Close();
		br.Close(); //hierfür gibt es kein Dispose
		fs.Close();
	}
}

10.02.2007 - 22:23 Uhr

Original von herbivore
Deshalb sind beide Erfahrungen (FH: man kriegt alles beigebracht und Uni: man muss sich selber kümmern) gleichermaßen richtig.

In der FH wird einem nicht immer alles beigebracht. Es hängt stark vom Prof ab. Es hängt auch davon ab, wie viele Studenten im Raum sitzen, bei manchen Studiengängen / Fächern werden auch regelmäßig große Hörsääle belegt. Dieses Semester hatten wir ca. 200 Wirschaftsinformatiker (und ca. 45 Informatiker, zu denen ich mich zählen kann). Wirklich didaktischen Unterricht wird man in der FH kaum haben, außer vielleicht in höheren Semestern, wenn die Zahl der Studenten schon stark gesunken ist. Man lernt aber meist schon recht viel durch die Vorlesungen, das ist richtig, und das halte ich auch für sinnvoll, weil sonst bräuchte man gleich keine Vorlesungen anbieten. Ich studiere selbst an der FH, aber wenn man zu Hause überhaupt nichts programmiert, wird man eine Prüfung in einem Programmieren-Fach mit sehr großer Wahrscheinlichkeit nicht bestehen. Die Vorlesungen sind halt trotzdem fast ausschließlich theoretisch. Natürlich könnte es sein, dass die FH-Theorie aus der Sichtweise eines Uni-Studenten viel mehr Praxisbezug hat, als das was sie aus ihren Vorlesungen kennen.
Ich bereue es überhaupt nicht, an die FH gegangen zu sein. Ich sehe nur Vorteile gegenüber der Uni. Natürlich sehen das viele anders.

Um das ganze nicht zu einem Offtopicgequatsche verkommen zu lassen: Eine Begleitlektüre macht oft Sinn, auch wenn man an der FH ist. Wo wir wieder beim Thema wären: Gibts weitere Buchempfehlungen?

10.02.2007 - 02:34 Uhr

Original von herbivore
zu 1. Der Unterschied ist eben, dass nicht nur native C++ sondern auch C++/CLI und managed C++ unterstützt werden.

Okay, und ansonsten werden wahrscheinlich standardmäßig ein paar Libraries von Microsoft dabei sein, es darüber hinaus aber nur geringe Unterschiede zum C++ in anderen Entwicklungsumgebungen geben, oder?

Original von herbivore
zu 2. Ich denke
>
beantwortet schon einen Menge.

Okay, dann bleibt noch die Frage, ob das Programmieren mit C++/CLI im Allgemeinen einfacher oder schöner ist, als mit purem C++. In C++/CLI kann man ja auch puren C-Code verwenden, aber wenn man C/CLI-Code verwendet, ist dieser Code dann übersichtlicher oder handlicher, wenn man ihn mit C++-Code vergleicht?

Die restlichen Fragen sind eigentlich schon gut beantwortet. Danke 🙂.

10.02.2007 - 01:24 Uhr

Ich habe mal ein paar grundsätzliche Fragen zu C++:

  1. Was zeichnet Visual C++ aus? Ist das nur eine Entwicklungsumgebung, oder hat Microfisch da auch was an der Sprache verändert?

  2. Was ist der Unterschied zwischen managed C++, unmanaged C++ und C++/CLI (grob gesagt)?

EDIT: Zu Frage 2: Gehe ich richtig der Annahme, dass C++/CLI eine Weiterentwicklung von managed C++ ist und dass beide eine relativ neue (starke?) Abwandlung vom unmanaged C++ darstellen? Für unmanaged C++ braucht man kein Dotnetframework, dafür ist sein Code unübersichtlicher als C++/CLI-Code und im Allgemeinen ist das Programmieren damit schwerer?

  1. Sowas wie einen Garbage Collector gibts in C++ gar nicht, oder?

  2. Gibt es große Unterschiede, wenn man C++-Programme für Windows oder für Linux schreibt? Braucht man jeweils spezielle Bibliotheken, oder ändern sich auch grundsätzliche Dinge?

10.02.2007 - 01:17 Uhr

Original von MrSparkle
Aber das müßtet ihr doch alles in dem Kurs erklärt kriegen. Oder bist du so ein Streber, der sich nur in ein Seminar reinsetzt, wenn er alles schon weiß? ggg

Naja, Informatikstudium ist halt auch zu einem gewissen Teil Selbststudium. Deswegen wär ein gutes Buch nicht schlecht.

Danke schon mal für die bisherigen Beiträge, und auch für das Beileid 😉.

09.02.2007 - 15:24 Uhr

Ich muss / darf mich im nächsten Semester mit C++ herumschlagen. Kann mir jemand eine Internetseite oder ein Buch empfehlen, die bzw. das den Einstieg in C++ erleichtert, wenn man davor schon C# (und Java) programmiert hat? Im Internet habe ich bisher nur oberflächliche Sachen, aber keine wirklich nützliche Dinge in dieser Hinsicht gefunden.

07.02.2007 - 19:18 Uhr

Wenn ich das alles so lese, installier ich das Sp1 nicht. Bisher sind bei mir keine größeren Probleme bei Visual Studio aufgetaucht. Wenn ich nun das Sp1 installiere, würde ich Gefahr laufen, dass das Studio schlechter läuft als vorher. Außerdem habe ich momentan zu wenig Speicherplatz frei für so ein riesiges Service Pack.

Mein Fazit: Solange das Visual Studio mir keine Probleme bereitet, kommt das Sp1 nicht drauf.

07.02.2007 - 19:08 Uhr

Original von herbivore

Ein Property macht normalerweise nur Sinn, wenn die Klasse auch ein entsprechendes (privates) Feld dazu hat.
Nein, dass muss nicht sein, z.B. könnte man in einer Datum-Klasse ein Feld iTageSeitErstenErstenEins haben, aber als Properties Tag, Monat und Jahr.

Okay, überzeugt.

Jetzt ist mir alles klar. Vielen Dank.

07.02.2007 - 16:35 Uhr

Original von Traumzauberbaum
Es gilt die Regel: Alle Namen die irgendwie für andere Assemblies sichtbar sind (also public, protected) dürfen sich nicht nur durch Groß-/Kleinschreibung voneinander unterscheiden. Das liegt daran, dass die Assemblies sprachunabhängig sind, und nicht alle Sprachen die Groß-/Kleinschreibung unterscheiden, wie VB z.B.

Danke. Das ist ein interessanter Aspekt, an den ich noch gar nicht gedacht habe. Ehrlich gesagt, habe ich mich noch nicht damit beschäftigt, wie man von einer Assembly auf die "Elemente" einer anderen Assembly zugreifen kann. Da muss ich mich mal informieren.

@herbivore:
Okay, ich glaube ich habe verstanden, wann statt Properties Getter/Setter benutzt werden sollten. Wenn man ein Property benutzt, dann sollte das auch wirklich eine Eigenschaft des Objekts sein. Wenn aber das Objekt z.B. nur irgendwelche Berechnungen durchführt, dann wäre ein Getter angebrachter, weil der zurückgegebene Wert nicht als Eigenschaft des Objekts angesehen werden kann. Dementsprechend wären Set-Methoden eigentlich unsinnig. Mir fällt zumindest kein Beispiel ein.
Anderer Ansatz: Ein Property macht normalerweise nur Sinn, wenn die Klasse auch ein entsprechendes (privates) Feld dazu hat.
Korrigier(t) mich bitte, wenn ich falsch liege.

Noch eine letzte Frage: Es ist in C# schon üblich bei Get- und Set-Methoden "Get" bzw. "Set" ausdrücklich hinzuschreiben, oder? Also z.B. GetName(), SetName(..).

07.02.2007 - 15:27 Uhr

Ich denke, das wäre insofern sinnvoll, damit eine Methode Überladungen mit verschiedenen Sichtbarkeiten haben kann.
Durch Überladung kann man die Sichtbarkeit nicht ändern, denn jede Überladung ist eine eigenständige Methode (gleichen Namens).

Da hast du mich falsch verstanden. Ich hab schon das gemeint, was du geschrieben hast.

Properties können nicht überladen werden.

Okay. Leuchtet mir jetzt nachträglich auch ein, weil es ja bei Properties keine Parameter gibt.

Felder: Wann PascalCase, wann camelCase (public, private, protected, static)?
Immer camelCase (außer bei Read-only Static Feldern).

Welchen Sinn hat diese Ausnahme? Spielt es hierbei keine Rolle, welche Sichtbarkeit das Feld hat?

Konstanten: Alle Buchstaben groß, oder nur wenn sie maximal 2 Buchstaben haben, sonst PascalCase?
Immer PascalCase!

Hm. Microsoft schreibt doch auch System.Math.PI statt System.Math.Pi? Oder gibts etwa im Framework ein kleines Durcheinander?

Sollte man allgemein alle lokal in Methoden definierte Objekte (egal welchen Typs) klein schreiben?
Nein, wichtig ist die Art des Members, nicht seine Sichtbarkeit.

Also nur die primiten Datentypen wie int? Bei "binaryWriter1 = new BinaryWriter(fs);" (in irgendeiner Methode lokal definiert) dürfte man deiner Meinung nach das binaryWriter1 nicht klein schreiben (damit habe ich camelCase gemeint)? Jetzt bin ich verwirrt.

Sollte man immer anstatt Get- bzw. Set-Methoden Properties verwenden, oder spricht da etwas dagegen?
Man sollte in der Regel Get- und Set-Methode vermeiden und Properties verwenden. Allerdings ist die eigentliche Trennline, ob das Member aus Sicht des Benutzers der Klasse den Zustand des Objekts repräsentiert.

Hm, das verstehe ich nicht. Kannst du bitte mir ein Beispiel hierzu geben?

Danke schon mal für die Antwort.

07.02.2007 - 14:37 Uhr

Also, als ich im Internet nach Empfehlungen gesucht habe, wie man einzelne Elemente aus C# schreiben sollte, bin ich auf unterschiedliche Antworten gestoßen. Mir sind Schreibweisen wichtig, die sich als nützlich bzw. übersichtlich erwiesen haben. Mir ist also nicht wichtig, wie dass offiziell von Microsoft empfohlen sein mag. Da wird ja empfohlen, fast alles in PascalCase zu schreiben. Da frage ich mich, wie soll das helfen, die Übersichtlichkeit zu fördern, wenn fast alles gleich aussieht? Vgl.: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconcapitalizationstyles.asp

Meine Fragen hierzu:

Sollte man Methoden immer in PascalCase schreiben, egal ob sie private, public, protected etc. sind? Ich denke, das wäre insofern sinnvoll, damit eine Methode Überladungen mit verschiedenen Sichtbarkeiten haben kann.

Sollte man Properties immer in PascalCase schreiben, auch wenn sie private sind (oder protected)? Dafür würde sprechen, dass man das Property überladen könnte und so eine Version für "außen" (public bzw. internal) und eine für "innen" (private bzw. protected) zur Verfügung stellen könnte.

Felder: Wann PascalCase, wann camelCase (public, private, protected, static)? Vielleicht immer camelCase, damit man ohne Probleme für jedes Feld ein Property mit dem gleichen Namen, jedoch im PascalCase schreiben kann?

Konstanten: Alle Buchstaben groß, oder nur wenn sie maximal 2 Buchstaben haben, sonst PascalCase?

Sollte man allgemein alle lokal in Methoden definierte Objekte (egal welchen Typs) klein schreiben?

Noch eine allgemeine Frage: Sollte man immer anstatt Get- bzw. Set-Methoden Properties verwenden, oder spricht da etwas dagegen? Macht es Sinn, ein Feld als readonly zu deklarieren, statt ein Property auf Get zu beschränken bzw. nur eine GetMethode zur Verfügung zu stellen?

20.12.2006 - 23:10 Uhr

Danke für die Antworten. Da die Dateien nicht all zu groß sind, werde ichs wohl so machen, wie ich in meinem ersten Post vorgeschlagen habe.

Die Dateien sollten nicht größer als ca. 1 MB sein, dann wird es wohl am schnellsten gehen, wenn ich die zu kopierenden Daten komplett in den Speicher einlese mit StreamReader.ReadToEnd() und dann mit StreamWriter.Write(...) wieder schreibe. Die Puffer von StreamReader und StreamWriter werde ich auf Standardgröße lassen.

Wenn jemand hierzu noch irgendwelche Verbesserungsvorschläge hat, dann kann er sie gerne posten. 🙂

20.12.2006 - 22:13 Uhr

Stellt das .net-Framework eine Möglichkeit bereit, irgendwie in die Mitte einer Textdatei Zeichen / Bytes einzufügen, ohne dabei andere Zeichen zu überschreiben (speziell bei C#)? Mit dem Write() des BinaryReaders werden ja einfach die nachfolgenden Bytes überschrieben.

Wenn nicht, könnte ich doch folgendes machen: Ich bestimme, wie viel Zeichen hineingeschrieben werden sollen, verlängere die Datei um diese Anzahl an Bytes und schiebe dann die ganzen Bytes ab der Einfügestelle um so viele Bytes nach hinten. In dem frei gewordenen Platz schreibe ich dann die Zeichen hinein.
Oder gibts da bessere (perfomancefreundlichere) Ansätze?

30.11.2006 - 20:22 Uhr

Erst mal vielen Dank für deine Antworten.

Original von herbivore
Anm.: Was du Attribute nennst heißt in C#-Terminologie Properties/Eigenschaften.

In dem guideToCsharp (die aktuelle pdf-Version, "Buchseite" 134) wird zwischen Datenfeldern und Eigenschaften unterschieden, wobei bei Eigenschaften set{} und / oder get{} steht und bei Datenfeldern nicht. Ich wollte mit "Attribute" Datenfelder und Eigenschaften zusammenfassen. Ist eine solche Unterscheidung wie im guideToCsharp überhaupt gebräuchlich, oder habe ich da nur was falsch aufgefasst?

Original von herbivore
Anm.: Wegen der Fragen 3, 4, 5, 7 und 9: Wichtig ist, dass man die Klassen so designt, dass das Modell möglichst gut die Wirklichkeit abbildet. Man sollte sich nicht so sehr von technischen oder Implementierungs-Aspekten leiten lassen. Vererbung sollte man z.B. dann einsetzen, wenn die Klassen in der wirklichen Welt in der "IST-EIN"-Beziehung stehen, z.B. ein Affe IST-EIN Säugetier.

Dieser Tipp hilft mir sehr weiter. Danke. Ich ließ mich nämlich tatsächlich bisher zu stark von technischen Aspekten und Implementierunsaspekten leiten.

Den Sinn von Interfaces habe ich leider immer noch nicht verstanden. Ich glaube da hilft es nur, dass ich selbst herumprobiere, was Interfaces bewirken. Soweit ich weiß, kommt man aber normalerweise auch mit abstrakten Klassen allein aus, ohne Interfaces zu benötigen. Abstrakte Klassen habe ich verstanden.

Ich glaube, ich sollte mich einfach mal daran machen, meine Programmidee auf Klassen und Objekte abzubilden, das ganze also grob zu "modellieren".

29.11.2006 - 22:49 Uhr

Hi.

Als mein nächstes Projekt möchte ich einen Leveleditor für ein älteres Dos-2D-Jump&Run-Spiel schreiben. Wie das Format der Leveldateien aufgebaut ist, habe ich schon entschlüsselt und ich habe auch schon Bilder für die "Tiles" ("Fliesen").

Jetzt muss ich mir Gedanken zur Struktur des Programms machen. Ich habe mir vorgenommen, den Code streng objektorientiert zu gestalten. Leider habe ich nicht viel Erfahrung mit OOP. Deswegen weiß ich nicht so recht, wie ich das Programm strukturieren soll.

Ich erläutere mal kurz, wie ich mir das fertige Programm in etwa vorstelle:

Es gibt ein Hauptfenster, in dem ich mehrere Unterfenster öffnen kann. Das Hauptfenster enthält ein Menü.

In einem Unterfenster wird der aktuelle Levelentwurf dargestellt, indem für jedes Tile ein bestimmtes Bild angezeigt wird (alle Tiles haben dieselbe Größe und sind quadratisch). Gleiche Tiles haben das gleiche Bild. Bei jedem Unterfenster wird außerdem eine Scrollleiste angezeigt, mit der man ein bestimmtes Tile auswählen kann (welches dann in einer Vorschau angezeigt wird) und man dann ein Tile dieser Art durch Klicken auf eine Stelle in der Map setzen kann.

Dann gibt es noch ein Vorschaufenster, in dem das aktuell ausgewählte Unterfenster in klein angezeigt wird.

Schließlich kann man über das Menü bestimmte Dialogfenster öffnen, z.B. eines mit dem man eine neue leere Map erstellen kann oder die Größe einer Map verändern kann.

Wenn man eine Datei öffnet, dann wird der Inhalt der Leveldatei in ein verarbeitbares Format umgewandelt, bevor ein Level angezeigt werden kann. Umgekehrt läuft auch ein Converter, wenn man einen Level abspeichert.

Jetzt haben sich mir ein paar Fragen aufgedrängt (ich benutze VS 2005 Prof.):

  1. In wie viele .cs-Dateien sollte ich den Programmcode aufteilen? Sollte jede Klasse eine eigene cs-Datei haben, oder sollten sich inhaltlich zusammengehörende Klassen eine cs-Datei teilen? Ist eine Program.cs sinnvoll, welche z.B. die Main()-Funktion beinhaltet, oder sollte ich solche Dinge lieber in die .cs-Datei des Forms des Hauptfensters schreiben?

  2. Wenn man mit dem Formdesigner arbeitet, ist der Code jeder Form ja auf 2 Dateien verteilt. Mir gefällt aber diese Aufteilung nicht besonders. Kann ich irgendwie die Aufteilung umgehen, aber gleichzeitig den Formdesigner noch normal nutzen (z.B. das Erstellen von Ereignissen)? Könnte ich z.B. meinen Code einfach in die entsprechende .Designer.cs-Datei schreiben? Kann man einstellen, welchen Dateinnamen Codes vom Formdesigner erstellte Forms bekommen? Also zum Beispiel, dass das ".Designer" wegfällt?

  3. Sollte man generell möglichst viel mit Vererbung arbeiten?

  4. Sollte man statische Attribute und Methoden möglichst vermeiden?

  5. Wann ist es sinnvoll, abstrakte Klassen und/oder Interfaces zu verwenden? Allgemein, wenn man erzwingen will, dass eine abgeleitete Klasse bestimmte Methoden bzw. Attribute enthalten muss?
    Habe ich es eigentlich richtig verstanden, dass bei der Ableitung von abstrakten Klassen die Attribute einfach übernommen werden, man bei Interfaces aber verpflichtet wird, die Attribute explizit in die Klasse hinzuschreiben? Ich meine hier ausdrücklich die Attribute, nicht die Methoden.

  6. Ist es üblich, einer Klasse Objektinstanzen einer davon abgeleiteten Unterklasse als Attribute zuzuteilen und so mit der Klasse die Objekte der Unterklasse verwalten zu können?

  7. Sollte man eher nach dem Schema arbeiten, dass eine Oberklasse ziemlich viele Methoden besitzt und man dann diese bei abgeleitenden Klassen überschreibt, oder nach dem Schema, dass man einer Oberklasse relativ wenig Methoden zuteilt und dann bei den abgeleitenden Klassen neue Methoden hinzufügt, anstatt Methoden zu überschreiben?

  8. Gibt es Beispiele, wann ein sealed sinnvoll sein könnte?

  9. Sollte man vermeiden, in einer Klasse sowohl statische als auch nichtstatische Attribute bzw. Methoden zu definieren?

Ich hoffe, ihr könnt mir bei diesen allgemeinen Fragen weiterhelfen. Später werde ich dann noch einen Vorschlag posten können, in dem ich aufführe, wie die einzelnen Objekte speziell bei dem Leveleditor zusammenhängen könnten.

Ich freue mich auf eure Antworten.

26.10.2006 - 17:14 Uhr

Original von Friedel
Hallo Red_Wraith,

Form.ShowDialog();  

Vielen Dank! Dass die Lösung soo einfach ist, hätte ich auch nicht gedacht.

26.10.2006 - 17:02 Uhr

Bei meinem Programm wird beim Start eine Hauptform (die eigentliche GUI des Programms) und eine Nebenform (ein about-Fenster mit ein paar Infos) geladen. Die Nebenform wird zunächst versteckt und wenn man auf einen Button der Hauptform klickt, wird die Nebenform angezeigt. Wenn man die Nebenform schließt, wird das Fenster wieder versteckt anstatt geschlossen zu werden (das OnClosing-Ereignis habe ich überschrieben).
Das alles funktioniert so, wie es sollte.

Leider weiß ich nicht, wie ich verhindere, dass der Benutzer das Hauptfenster auswählen kann, wenn gerade das Nebenfenster offen ist. Ich will also den gleichen Effekt wie bei einer Messagebox erreichen, denn da kann man auch nicht das Hauptfenster auswählen, solange die Messagebox offen ist.

24.07.2006 - 22:13 Uhr

Original von Lord Hessia
Mal überlegt, dass das ganze ohnehin Schwachsinn ist, da immer true? 😄

Ach ja, stimmt. Lol. 😁

Original von Lord Hessia
Wenn Du aber so etwas machen willst:

if (variable1 != "bla" && variable1 != "blubb" && variable 1 != "boing") {  
}  

Dann geht das indirekt irgendwie schon:

  
switch (variable1) {  
  case "bla":  
  case "blubb":  
  case "boing":  
    break;  
  default:  
    // hier die anweisung hin, die im if-block steht  
    break;  
}  
  

Bzgl. der Diskussion zur switch-Syntax: Bei mir ist der Code, den ich oben stehen habe erlaubt. Nur wenn ich nach dem case irgendetwas andereas als ein neues case schreibe und am ende kein break kommt, dann meckert der Compiler. Das Trennen per Komma case "a", "b" usw. geht hingegen nicht.

So funktionierts bei mir auch. Die Schreibweise mit den Kommas geht bei mir (leider) auch nicht (die wäre noch kürzer). Ich nutze VC# 2005 Express, .net 2.0.

Mir ist gerade noch eine Lösungsidee gekommen (das kann man natürlich dann auch umkehren):


string variable1 = "bli";
string[] testArray = new string[4] { "bla", "ble", "blo", "blu" };
if (Array.BinarySearch(testArray, variable1) < 0) {
	System.Diagnostics.Trace.WriteLine("variable 1 ist nix von alldem");
}

Die fette If-Abfrage kann man also durch das Einrichten und Durchsuchen eines Arrays ersetzen. Das sind auch nur 2 Zeilen.

23.07.2006 - 14:59 Uhr

Original von -acid-
Also:

  • Das Menü funktioniert mit dem Renderer.System bei 2000

Eben nicht. Da geht es auch nicht. Du hast doch einen Screenshot von Windows 2000 gepostet: In Windows 98 sieht alles anders aus

?(

21.07.2006 - 23:33 Uhr

Original von Red_Wraith
Ungleichheit wie im folgenden Beispiel kann man nicht über switch-case regeln, oder❔

  
if (variable1 != "bla" || variable1 != "blubb" || variable 1 != "boing") {  
}  

Ich war mit meiner Vermutung wohl richtig, weil keiner dazu Stellung genommen hat?

Es gibt also kein:


switch (variable) {
case !"bla":
...
break;
....

21.07.2006 - 23:28 Uhr

Original von sbertl000
Unterscheiden kannst du trotzdem nach NT-Version unterscheiden:

5.0 = Windows 2000
5.1 = Windows XP
5.2 = Server 2003
6.0 = Windows Vista

Und alles frühere kannst du nach Dos-Version unterscheiden.

Achso, alles klar! Danke.

acid, mit deinem letzten Post kann ich nichts anfangen. Es genügt nämlich nicht, nur nach NT und nicht-NT zu unterscheiden. Man muss nämlich auch die NT-Version unterscheiden (was mir seit dem oben zitierten Post klar geworden ist).

21.07.2006 - 01:30 Uhr

Original von -acid-
Klaro. Ich will ja nicht nach W2k / XP unterscheiden, sondern nach NT und nciht NT 😉

Aslo ist es das was er brauch.

Nein, leider nicht. Ich müsste eher unterscheiden: XP oder nicht XP. Der Grund dafür: Ein bestimmtes Problem mit dem Menü tritt bei Win98 UND Win2000 auf, bei XP aber nicht. Vgl.: In Windows 98 sieht alles anders aus

19.07.2006 - 03:11 Uhr

Ich arbeite bei meinem Programmen relativ häufig mit try und catch.

Ist das eurer Meinung nach ein schlechter Programmierstil, weil man lieber den Code so ausfeilen sollte, dass gar keine Exceptions mehr möglich sind und man somit auf try und catch verzichten kann?
Oder sollte man doch lieber ein try und catch mehr setzen, als eins zu wenig zu haben und damit einen kompletten Programmabsturz bei Exceptions zu riskieren, mit denen man nicht gerechnet hat?

Haben try und catch einen negativen Einfluss auf die Performance?