| 

.NET C# Java Javascript Exception

11
Hallo liebe CK-Com,

Ich wollte mal nachhaken, ob es Möglich ist, eine Methode eines Interfaces mit Regeln zu belegen und Exceptions zu werfen (bzw. gar das Kompilieren zu verhindern), wenn sich nicht an diese Regeln gehalten wird.

Folgender Anwendungsfall:
public interface IInterface
{
public string getSupportMail();
}

public class CClass : IInterface
{
public string getSupportMail()
{
return string.Empty;
}
}
Mein Ziel ist es, genau das hier gezeigte Szenario zu verhindern. Ich möchte also der Methode getSupportMail() in meinem Interface eine Regel mitgeben, die besagt, dass die geerbte Methode niemals einen leeren String zurückgeben darf.

Entsprechend natürlich auch für andere Datentypen und mögliche Rückgabewerte (Bsp. null soll auch nicht zurückgegeben werden dürfen)

so far
Karill
News:
01.02.2012
Karill Endusa 1,5k 1 9
4 Antworten
7
Hi Karill,

statisch geprüfte Code Contracts könnten hier helfen. In Deinem Beispiel wäre "darf niemals einen leeren String zurückgeben" Post-Condition der Methode. Mit den CodeContracts kannst Du das auch schön für ein interface definieren.

Für weitere Hintergründe DbC (Design by Contract) oder Code Contracts googlen. Oder einfach nochmal nachfragen...

Gruß
Florian
01.02.2012
ffordermaier 8,4k 3 9
Super, danke... meinen ersten Eindrücken nach genau das was ich gesucht habe, und sogar zur compilezeit... was will man mehr :) sollten dazu noch Fragen aufkommen, melde ich mich wieder.
Fürs Erste aber: Danke, danke vielmals.
Karill Endusa 01.02.2012
Wieder was gelernt..
Nicolai Schönberg 01.02.2012
5
Sowas kann man mit Hilfe von Code Contracts erreichen.

Code Contracts

Kurzüberblick als Video:
Mike Barnett and Daryl Zuniga: Code Contracts Editor Extensions

Eine Anleitung wie man das mit Interfaces umsetzt gibt's hier:

Interface contracts – forcing code contracts through interfaces

Viel Erfolg!
01.02.2012
Schon wieder zu langsam. *grml*
maximilian_becker 01.02.2012
+1 für die hilfreichen links.
ffordermaier 01.02.2012
Vielen lieben Dank dafür :-)
maximilian_becker 01.02.2012
4
Wenn die gewünschte Regel eher etwas mit dem Datentyp als mit der Methode zu tun hat und häufiger gebraucht wird, dann käme als Alternative auch noch in Betracht, einen eigenen Datentyp dafür zu definieren und diesen als Rückgabewert der Methode vorzuschreiben (und konsistent überall zu benutzen, wo die entsprechende Bedeutung gegeben ist).

Z.B. wäre

public struct NonEmptyString
{
private const string defaultValue = "non-empty default";
private string value;
public string Value
{
get { return value ?? defaultValue; }
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException();
else
this.value = value;
}
}

public static implicit operator string(NonEmptyString nes)
{
return nes.Value;
}
}

ein Wrapper für einen String, der niemals null und niemals leer ist und sich implizit in einen String konvertieren und damit fast wie ein solcher verwenden läßt. (Kleiner Haken: um nicht leer und nicht null gleichzeitig sicherzustellen, wird ein passender Initialwert benötigt. Ist das nicht möglich, müßte der getter eine IllegalStateException werfen, wenn der Nutzer die Initialisierung vergessen hat - oder das technische Erzwingen von "nicht null" wird dann besser aufgegeben.)

Wenn ein solches Vorgehen in Frage kommt, sollte man auch gleich überlegen, ob der Typ nicht eine fachliche Bedeutung hat. Technische Datentypen (wie mein Beispiel) neigen dazu, "mißbraucht", d.h. für andere als den ursprünglichen Zweck verwendet zu werden. Mal ganz abgesehen davon, daß "PLZ" auch leichter lesbar ist als "StringDerAusGenau5ZiffernBesteht".
02.02.2012
Matthias Hlawatsch 13,2k 4 9
+1 Ich würde Deinen Vorschlag sogar als Ergänzung sehen. Fachlich streng typisieren hat noch nie geschadet. Einziger Wermutstropfen bei Deinem Vorschlag ist die Auswertung zur Laufzeit.
Vlt noch eine Alternative: Wenn Du aus struct eine class machst, das Ganze immutable (ohne setter und readonly member) mit einem Konstruktor, der einen string akzeptiert, kann man sich die statische Prüfung schenken, weil by-design nur wie gewünscht verwendbar.
ffordermaier 02.02.2012
Die struct habe ich benutzt wegen "soll niemals null sein". Ich finde, es ist nur der halbe Erfolg, dafür zu sorgen, dass der gewrappte Wert nicht null sein darf, wenn aber der Wrapper null sein kann.
Sonst völlig d'accord. Immutable ist immer schön. Könnte man bei der Struct-Lösung erreichen, wenn man statt des Setters einen Konstruktor spendiert. Wenn dann jemand den Standard-Konstruktor benutzt, hat er halt einen nicht mehr änderbaren Default-Wert - das fällt beim Kodieren schnell auf.
Matthias Hlawatsch 02.02.2012
1
Stimmt, das hab ich übersehen. Zusammen mit diesem Hinweis würde ich sagen, dass die Modellierung als immutable class zusammen mit einer trivialen PostCondition [ret != null] die Sache am Besten abbildet. Fachlichkeit steckt im Typ (und nicht im Contract des Verwenders), Verwendung als not-null im Contract des Verwenders, der das fordert. Schöne Sache.
ffordermaier 02.02.2012
Ja, das hört sich gut an.
Matthias Hlawatsch 02.02.2012
tschuldige dass ich mich jetz erst dazu äußere :)
Also:
Sehr schöne Lösung, gefällt mir auch sehr gut (+1) und ich werde auch diese in Betracht ziehen für die endgültige Verwendung!
Karill Endusa 03.02.2012
0
Hm nee, so geht das nicht. Interfaces sind nicht dafür da um irgendwelche Regeln zu definieren.

Du könntest dir eine Hilfs-Klasse schreiben und diese in deinem Interface Nutzen.

public class Message
{
private string message;
public Message(string msg)
{
message = msg;
}

public string GetMessage()
{
if (string.IsNullOrEmpty(message))
{
throw new ArgumentOutOfRangeException("message can not be null or empty");
}
}
}


Und dann halt in deinem interface nicht string sondern Message verwenden
01.02.2012
Nicolai Schönberg 2,4k 2 9

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH