2016-06-25 19 views
3

das folgende Problem Betrachten geworfen hatteErteilung einer Referenz auf eine Instanz, deren Konstruktor eine Ausnahme

Wenn ein Rahmen entwerfen, eine Schnittstelle ein Ereignis Aussetzens

präsentiert
interface I 
{ 
    event MyEventHandler MyEvent 
} 

Diese Schnittstelle wird schließlich von vielen implementiert werden verschiedene Drittanbieter und können von verschiedenen Kunden konsumiert werden.

Da jeder Anbieter neu kann das Ereignis args mit ungültigen Daten auf, die nur die Kontrolle Ich habe als ein Framework Autor auf der Veranstaltung args Ebene ist, so dachte ich an folgendem Schema:

class MyEventArgs 
{ 

public int? MyProperty{get;} 

MyEventArgs(int arg) 
{ 

    if(arg.IsInvalidArgument())//Let's pretend that there's such an extension method 
    throw new ArgumentException(...) 

    MyProperty = arg; 
} 

Dadurch wird sichergestellt, dass ein Client ungültige Werte nicht verwenden kann, die von einem bösartigen Codeabschnitt bereitgestellt werden, da der Konstruktor eine Ausnahme auslöst. Daher wird der Ganzzahl kein Wert zugewiesen, wodurch sie zu einer Nullreferenz wird.

Doch dies schafft auch Overhead in Client-Code, da jetzt der Client den HasValue zu prüfen hat und Zugriff dann Wert, so dass das eventargument weniger benutzerfreundlich .. Dies wird noch umständlich, wenn die Menge von Parametern pro Ereignisargument wächst.

ich technisch könnte das Fragezeichen, zu entfernen, die den Client des Nullable Unsinn befreien würde, da es meiner Meinung nach keine Möglichkeit, auf Gottes grüner Erde ist ein Verweis auf eine solche Instanz zu erhalten, aber das Problem ist, dass Dieses Szenario, obwohl es leicht zu testen ist, kann Randfälle haben, an die ich nie gedacht habe, daher meine Frage.

Gibt es eine Möglichkeit, einen Verweis auf eine Instanz zu erhalten, deren Konstruktor eine Ausnahme ausgelöst und an die Ereignislistener übergeben hat?

+0

Es ist mir wirklich unklar, was Sie zu fragen versuchen. Zuallererst, über was "Overhead" sprichst du? Zweitens, welche "Referenz" möchten Sie genau erhalten? – CodeCaster

+0

@CodeCaster Ich habe meine Frage bearbeitet. Danke, dass Sie mir die Unklarheit zur Kenntnis gebracht haben. Der Overhead besteht darin, die Nullable-API für jede Eigenschaft in der Ereignisargumentklasse zu verwenden. Der Verweis ist eine Referenz, deren Konstruktor eine Ausnahme ausgelöst hat. –

Antwort

3

Wenn ein Konstruktor eine Ausnahme auslöst es keine Möglichkeit, eine Referenz auf das Objekt zu erhalten (außer wenn das Objekt kooperiert mit thisvor Wurf Austeilen, nicht wahrscheinlich, schlechtes Design).

Aus diesem Grund ist Ihr ungültiges Objekt nicht erreichbar. Sein Zustand ist tatsächlich ungültig (Standard initialisiert), aber niemand kann ihn sehen. Es ist wie eine virtuelle Maschine, die auf der Innenseite beschädigt ist und versucht, Raketen zu starten, aber Sie haben die virtuelle NIC deaktiviert.

Dieses Muster wird überall verwendet. Du hast es oft benutzt, ohne es zu merken. Wenn Sie beispielsweise new FileStream(null) sagen, wie erhalten Sie einen Verweis auf diesen ungültigen Stream? Du kannst nicht.

Tun Sie einfach die normale Sache. Es ist gut, dass du das durchdacht hast.

Gibt es eine Möglichkeit, einen Verweis auf eine Instanz zu erhalten, deren Konstruktor eine Ausnahme ausgelöst und an die Ereignislistener übergeben hat?

Nein, aber hier ist ein Beispiel, wo es möglich:

class C { 
public static C Instance; 
public C() { 
    Instance = this; //publish/leak 
    throw ...; 
} 
} 

Nur nicht das tun. Das ist sowieso unnatürlicher Code. Der Konstruktor eines Objekts sollte normalerweise nicht viel tun, es sollte das Objekt in einen gültigen Zustand bringen und keine Nebenwirkungen verursachen. Nebenwirkungen sind die einzige Möglichkeit, einen Verweis auf this zu veröffentlichen.

Es gibt noch einen Haken: Ein Finalizer wird für dieses Objekt aufgerufen, wenn eines vorhanden ist. Finalizer sind selten, weil die nicht verwalteten Ressourcen in den meisten Fällen von Handle-Klassen gehalten werden sollten. Aus diesem Grund tritt dieses Problem selten in Kraft. Ein Finalizer kann jedoch den privaten Status seines Objekts sehen. Stellen Sie sicher, dass es damit umgehen kann. Der Finalizer wird wahrscheinlich auf abgebrochene Initialisierung prüfen und nichts tun.

0

Um Ihre Frage zu beantworten. Nein. Sie können keine Nullergebnis, wenn ein Fehler in einem Konstruktor angetroffen wird

Aber ich denke, die beste Art und Weise um dieses ist eine statische Funktion Konstruieren an die MyEventArgs Klasse hinzuzufügen

public static int DEFAULT_ARG = 1;//you can set this to whatever you want 
public static Create(int arg) 
{ 
    if(checkArg(arg)) 
    { 
     return new MyEventArgs(arg); 
    } 
    return new MyEventArgs(MyEventArgs.DEFAULT_ARG); 
} 

Dann anstatt das Konstruktor Verzeichnis mit var event = new MyEventArgs(arg); verwenden verwenden Sie var event = MyEventArgs.Create(arg);

Es ist ein bisschen wie ein Stress dieser Methode auf mehreren EventArgs verwenden, aber hey :) man kann immer ableiten sie alle aus der gleichen generischen abstrakten Klasse

this helps :)

+0

Danke für die Korrektur, aber ich sehe nicht, wie mir das hilft? Was ich versuche zu etablieren, ist, ob die Instanz erhalten werden kann, die ungültige Ereignisargument-Instanzen ermöglicht, trotz des Sicherheitsmechanismus zum Client-Code zu gelangen. –

+0

Ja, die Lösung wird sein, MyEventArgs (MyEventArgs.DEFAULT_ARG) anstelle von null zurückzugeben –

+0

Dies ist in der Tat eine Art Lösung, die ich jedoch vermeiden möchte, da dies jedes Event-Argument erfordern würde, um eine solche Funktion zu haben. Auch meine Frage erfordert keine Lösung, sondern eher eine Antwort in Form von Ja/Nein und warum. Ich danke dir für die Mühe. –

0

der Kunde hat das HasValue und dann Value es ist nicht notwendig, um die Eigenschaft ein Nullable<int> zu machen

Nun Zugang zu überprüfen, wie Sie es aus dem Konstruktor festlegen (vorausgesetzt, ein weggelassen private set), wo es nicht Nullable ist.

Gibt es eine Möglichkeit, einen Verweis auf eine Instanz, deren Konstruktor geworfen hatte, eine Ausnahme zu erhalten

Nein, wenn ein Konstruktor eine Ausnahme auslöst, die Sie nicht eine Instanz zurück.

+0

Es ist erforderlich, damit Eigenschaften nicht mit Standardwerten wie Null initialisiert werden, die in der Domäne der Eigenschaft gültig sein können. Deshalb lege ich es dort an erster Stelle. Was den Teil "Du bekommst keine Instanz zurück" angeht ... hast du etwas Konkretes, um dies zu untermauern? Ich neige dazu, das zu glauben, aber ich muss noch eine konkrete Antwort finden. –

+0

http://ideone.com/lDi9f7 – CompuChip

+1

@Eyal http://stackoverflow.com/questions/10119896/why-throwing-exception-in-constructor-results-in-a-null-reference. Über das NULL-Design kann ich im Moment nichts sagen. – CodeCaster

Verwandte Themen