Archiv für die Kategorie ‘C#’

Innere Werte

Mittwoch, 01. September 2010

Folgende kleine und gruselige “extension method” für C# habe ich aufgetan.

    public static Exception GetInnermost(this Exception ex)
    {
        Exception ActualInnerEx = ex;
        while (ActualInnerEx != null)
        {
            ActualInnerEx = ActualInnerEx.InnerException;
            if (ActualInnerEx != null)
                ex = ActualInnerEx;
        }
        return ex;
    }

Diese Methode soll die innerste Exception einer abgefangenen Exception ermitteln. Hier sieht man mal wieder wie umständlich etwas im Grunde sehr einfaches umgesetzt werden kann.

Übung: Wie könnte man diese Methode besser und schöner gestalten?

(weiterlesen…)

Was wir von einer Klotür lernen können…

Mittwoch, 01. Juli 2009

In der Informationstherorie ist die kleinste mögliche Informationseinheit ein Bit! 0 oder 1, An oder Aus, Offen oder Zu, Wahr oder Falsch. Alles mögliche Darstellungsformen, genauergesagt Interpretationsformen dieser minimalen Informationseinheit. Eine funktionierende Klotür kann nur Offen oder Verschlossen sein. Aber es existieren mehrere Interpretationsmöglichkeiten, die sich auf diesen Zustand beziehen. Wenn ich aufs Klo möchte, interessiert mich natürlich ob eine Kabine Frei oder Besetzt ist, da ich natürlich eine dieser Kabinen verwenden möchte. Befinde ich mich bereits in einer Kabine, so interessiert mich nicht mehr ob diese Kabine frei ist, denn ich weiss ja das sie es nicht mehr ist, ich bin ja schliesslich drin. Aber mich interessiert nun, ob die Tür Verschlossen oder Offen ist. Ich möchte ja schliesslich meinen Geschäftigkeiten ungestört nachgehen. Somit haben wir mehrere Interpretationsmöglichkeiten des Türzustandes. Dieser ist von dem Zustand abhängig, ob ich mich vor oder hinter der Tür befinde.

Wenn wir die Brücke jetzt zur Softwareentwicklung schlagen, könnte man das Vor bzw. Hinter der Tür als “Ich verwende eine Komponente” bzw. als “Ich entwickle eine Komponente” verstehen. Der Komponentenentwickler wird sich sicherlich für den Zustand interessieren, das eine Kabine besetzt ist, denn dann muss er mit den  ”Daten” irgendwas anstellen. Was kümmern ihn also die leeren Kabinen?

Jemand der diese Komponente jedoch verwendet, den interessiert nicht ob eine Kabine bereits besetzt ist. Ihn interessieren besetzte Kabinen nicht wirklich. Jemand der schon einmal enorm dringend aufs Klo musste, wird das nachvollziehen können. Uns interessieren in diesem Moment nicht die 15 Kabinen die Besetzt sind, uns interessiert genau die Kabine die in dem Moment frei ist.

Dies ist der Grund, warum wir in diesem Fall an der Komponenten-Schnittstelle kein Flag zur Verfügung stellen sollten, welches Kabine.IstBesetzt heisst. Dieses Flag sollte stattdessen Kabine.IstFrei heissen. Denn das interessiert den Anwender an dieser Komponente.

Der Komponentenentwickler sollte aber Intern mit dem Zustand arbeiten, den er am Häufigsten braucht (was hier der Zustand Kabine.IstBesetzt sein dürfte). Wie lösen wir dieses Dilemma? Ganz einfach, das Zauberwort heisst Kapselung. Nehmen wir als Beispiel einmal C# als Zielsprache. Dort können wir mit dem IstBesetzt intern arbeiten, bieten aber ein Property IstFrei an der Schnittstelle an:

Kabine.cs

Somit arbeitet jeder mit der Interpretation, die für ihn am Besten geeignet ist!

Diese Betrachtungsweise ist natürlich nicht nur auf Flags beschränkt! Dies gilt für alle Daten, Methoden und Properties die eine Schnittstelle nach außen offenlegt.

C driven C#

Mittwoch, 24. September 2008

Alte Gewohnheiten wird man oft nicht los, auch wenn es längst keinen Grund mehr gibt daran festzuhalten. So habe ich z.B. folgendes Konstrukt in unserem C#-Code gefunden, welches offensichtlich von einem eingefleischten C++ Programmierer kommt:

ClassA a = new ClassA();
if( a != null )
{
   …
}

Was in C++ noch Richtig war, ist in C# in dieser Art und Weise einfach Unsinn. In C++ konnte es natürlich passieren, wenn es keinen Speicher mehr gab, das der new-Operator als Ergebnis “NULL” lieferte. In C# jedoch wird in diesem Fall eine Exception “geschmissen”. Genauer gesagt die OutOfMemoryException. Was leicht in der MSDN nachgelesen werden kann. Sollte einem C/C++ Programmierer immer noch ein ungütes Gefühl beschleichen, steht einem ja ein Blick in die C#-Language-Specification offen, die ja bei Microsoft runtergeladen werden kann. Für die Sprachversion 1.2 ist im Kapitel 7.5.10.1 folgendes zu lesen:

AIf there is not enough memory available to allocate the new instance, a System.OutOfMemoryExceptionis thrown and no further steps are executed

Dort steht es also schwarz auf weiss. Sogar noch mit dem Hinweis, das keine Anweisung nach dem new Ausgeführt werden (was ja ein wesentlicher Teil des Exception-Handlings ist). Somit kann getrost auf die if-Abfrage verzichtet werden. Möchte man wirklich überprüfen ob nicht genug Speicher vorhanden war, kann man wie gewohnt mit try/catch die Exception abfangen. Über die Sinnhaftigkeit lässt sich vortrefflich streiten. Dies würde aber diesen Eintrag sprengen und muss nochmal an anderer Stelle etwas ausführlicher Diskutiert werden.

Bin ich noch null oder was?

Mittwoch, 24. September 2008

Da ich ja wieder mit einem Code-Review “beauftragt” wurde, mussten ja wieder Dinge für Coding-Horror abfallen. So wie auch folgendes kleines C# Konstrukt. Habe wieder alles Unnötige weggelassen. Man betrachte folgende kleine Klasse:

Image

Die Klassenvariable obj wird zuerst mit null initalisiert. Im Konstruktor wird dann überprüft, ob obj schon auf ein Objekt referenziert und wenn nicht, wird eine Instanz angelegt. Wenn wir mal in die C#-Language-Spezifikation sehen, steht dort was beim Instanziieren einer Klasse (Referenced-Type) passiert.

- A new instance of class T is allocated. If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.

- All fields of the new instance are initialized to their default values (§?5.2).

- The instance constructor is invoked according to the rules of function member invocation (§?7.4.3). A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.

Gehen wir also davon aus, das wir genug Speicher hatten und das Objekt tatsächlich angelegt werden konnte. Dann kann man dort nachlesen, das zuerst die Membervariablen (Fields) initialisiert werden. Das heisst in unserem Beispiel, das die Variable obj mit null Initialisiert wird (was auch defaultmässig passieren würde, wenn man das “= null“ weglässt) bevor der Konstruktor aufgerufen wird. Danach folgt gleich der Konstruktoraufruf. Dort wird dann auf null überprüft, was obj wie wir ja jetzt wissen “zwingend” sein muss. Somit ist diese Überprüfung im Konstruktor völlig seinfrei.

Die Initalisierung von obj kann also direkt in der Klasse erfolgen:

Dieses vorgehen hat aber einen Haken. Wenn die anzulegende Klasse (hier object) eine Exception schmeisst und diese in der eigenen Klasse (ObjectMania) abgefangen werden soll. Dann muss die Instanziierung im Konstruktor erfolgen:

Abschliessend nochmal zur Frage, ob es sinvoll ist obj mit null vorzubelegen. Im Prinzip wäre es egal, da alle neue Referenzen den Wert null haben. Von Microsoft wird jedoch empfolen, Variablen stets mit einem Defaultwert zu initalisieren (MCTS Kurs: 70-536).

Pseudodynamsicher l-value

Donnerstag, 29. November 2007

Ein System kann man ja nur von Innen heraus zerstören, deshalb habe ich mir überlegt wie ich zurückschlagen kann. Wenn ich die Menschen schon nicht dazu bringen kann, über ihren eigenen Code nachzudenken, so muss ich sie wenigstens dazu bringen sich über meinen Gedanken zu machen :-)

Mir ist aufgefallen, das viele Programmierer den “tertiären”-Operator ?: überhaupt nicht mögen. Ich finde richtig eingesetzt, ermöglicht er an vielen Stellen einfach schöneren und auch lesbareren Code. Aber da ja eine Aversion gegen diesen Operator zu herrschen scheint, habe ich mir ihn für die ersten Gegenschläge zum “Freund” gemacht #grins#

Folgendes kleines Konstrukt habe ich mir ausgedacht:

iTo < iLastTo ? iTo : iTi += fPrecision ? pi_i64SlaveRaster : pi_i64NetRaster;

Na was macht diese kleine Programmzeile? Ist doch nicht so schwer, oder? :-)

(weiterlesen…)

Wenn “de Morgan” leise graut…

Donnerstag, 24. Mai 2007

Heute bin ich in unserem Quellcode auf folgendes Schuckstück gestoßen:

if( x1 >= x2 || ( !( x1 < x2 || y1 < y2 ) && z1 >= z2 ) )
{
// Do other very crazy stuff
}

Als ich dies gelesen habe, hat mich sofort ein komisches Gefühl beschlichen ohne sofort zu wissen warum (Intuition?). Dann habe ich den Ausdruck mal näher untersucht.

Zuerst habe ich mal !( x1 < x2 || y1 < y2 ) aufgelöst.
Nach den Gesetzen von De Morgan ist !( A || B ) = !A && !B. Das ergibt:

!(x1<x2) && !(y1<y2)

Wenn jetzt x1<x2 bzw. y1<y2 wahr ist, so ist x1>=x2 bzw. y1>=y2 falsch. Daraus folgt:

!( x1 < x2 || y1 < y2 ) == x1 >= x2 && y1 >= y2

Dies setzen wir wieder in die gesamte Logikgleichung ein:

x1 >= x2 || ( x1 >= x2 && y1 >= y2 && z1 >= z2)

Dies entspricht dem Boolschen Ausdruck A || ( A && B && C ). Wenn A also true ist, ist perse der ganze Ausdruck wegen der Veroderung mit A true. Ist A false, so kann der ganze Ausdruck nur noch true werden, wenn A && B && C true wird. Da A in diesem Fall aber false ist, ist A && B && C auch immer false. Somit entspricht dieser Ausdruck einfach A.

Dies bedeutet, die obige if Anweisung kann auf folgende reduziert werden:

if( x1 >= x2 ) {…}

&& geht sogar in if(…)

Donnerstag, 15. März 2007

Dieser Beitrag ist wieder vom “Ist doch klar, sowas macht doch keiner”-Typus. Leider sieht die Sache ganz anders aus. Folgendes sehe ich JEDEN Tag häufiger:

ififif 1

Ganz schlaue Experten gehen sogar einen Schritt weiter und optimieren die Klammern weg, weil es Tipparbeit spart und “sinniger” erscheint:

ififif 2

Ich weiss nicht wie es anderen “Durchschnittsprogrammierern” geht wenn sie so etwas sehen, ich jedenfalls habe das Gefühl das sich meine Retina ablöst… Für alle die noch nicht gesehen haben, warum dies Augenkrebs verursachen kann, hier nochmal der Hinweis: Es gibt für logische Ausdrücke Boolsche-Operatoren. Jede Programmiersprache hält ein paar griffige bereit. Die Untermenge postuliere ich jetzt einfach mal auf UND, ODER und NICHT! In C/C++/C# werden sie mit &&, || bzw. ! ausgeschrieben. Eine saubere Formulierung dieser Abfrage wäre somit:

ififif 3

Eine Ausrede die ich diesbezüglich nicht mehr hören kann ist: Ja, früher hat ja in den if’s noch mehr dringestanden. Das ist dann alles nach und nach rausgefallen. DAS IST KEINE AUSREDE! DAS IST BULLSHIT! Wenn ich etwas aus/in einer if (oder sonstwo) lösche/ändere/hinzufüge, habe ich nicht nur das Privileg sondern auch die hoheitliche Pflicht sich den umgebenen Quellcode anzuschauen. Und sollte ich durch meine Änderungen ein solches Konstrukt “hinterlassen”, bin ich nicht besser als jener, der sowas initial in die Tastatur rotzt.

do while – Schleife

Donnerstag, 15. März 2007

In diesem Beitrag geht es um ein do – while Konstrukt, welches besser formuliert werden kann (gefunden in freier Wildbahn). Ich habe den Code-Teil wieder auf die wesentliche Struktur runtergebrochen:

do while hrmpf
Bevor Ihr weiterlest, könntet Ihr euch mal überlegen wie dieses Schleifenkonstrukt besser formuliert werden könnte.

(weiterlesen…)