2012-03-28 8 views
5

Ich habe eine Menge von Code-Stücken, die einmal während der Initialisierung ausgeführt werden müssen.Eine Sicherung mit einem Boolean

ich auf diese Weise einen boolean-Flag zu verwenden, weil es in einem Fall ist

bool _fuse; 

void PerformLayout() 
{ 
    Size size; 

    if (!_fuse) 
    { 
     size = _InitialContainerSize; 
     _fuse = true; 
    } 
    else 
     size = parent.Size; 

    // ... 
} 

Weil es oft geschieht, habe ich etwas dieses Boolesche Variable zu machen, um wie eine Sicherung:

Also tat ich dies:

bool _fuse; 

void PerformLayout() 
{ 
    Size size; 

    if (!Burnt(ref _fuse)) 
     size = _InitialContainerSize; 
    else 
     size = parent.Size; 

    // ... 
} 

Wenn es auf false initialisiert wird, sobald das Ergebnis der Abfrage false zurückgibt, machen den switc h zu wahr, und aufeinander folgende Aufrufe kehren wahr zurück.

Natürlich funktioniert es, aber ich bin nur mäßig zufrieden und ich bin mir sicher, dass es elegantere Lösungen gibt. Was wäre dein?

+2

'Rückgabewert || ! (Wert = wahr); '(nur Spaß!) –

+0

Interessant. Bis jetzt sind es drei Upvotes und drei Votes, die geschlossen werden müssen. –

+0

Keine echte Frage. Sollte auf einer Codereview-Site sein. Nicht hier. – leppie

Antwort

1

Ich denke, die allgemeine Stoßrichtung Wiederholung ist hier richtig (auch wenn die Wiederholung sehr klein zu vermeiden ist ... aber immer noch). kapseln Sie es einfach und nennen Sie es richtig:

struct InitializerGuard { 
    private bool hasRun; 

    public bool HasRun() { 
     if (hasRun) 
      return true; 
     hasRun = true; 
     return false; 
    } 
} 

Verbrauch:

InitializerGuard sizeInitializer; 

void PerformLayout() 
{ 
    Size size; 

    if (!sizeInitializer.HasRun()) 
     size = _InitialContainerSize; 
    else 
     size = parent.Size; 

    // ... 
} 

Aber wenn Sie sich mit diesem Muster sehr oft feststellen, könnte dies anzeigen, dass ein Refactoring in Ordnung ist. Vielleicht einigen Variablen nur Standardwerte zuweisen? Warum werden sie überhaupt nicht initialisiert?

+1

oder nur: 'Size size = HasRun()? parent.Size: _initSize; ' – leppie

+0

Dies ist elegant und klar. Ich mag das. Ich denke, ich werde das kopieren. (Vielleicht werde ich die HasRun-Methode stattdessen in eine Eigenschaft ändern?) - Ich könnte einen Teil meines Codes wahrscheinlich besser umgestalten, aber in vielen Fällen habe ich keine Wahl, weil es in einigen Ereignissen verwendet wird, und Code benötigt einige Init bei ihren erstes Feuer. – Larry

+1

@Laurent Eigenschaften dürfen keine Nebenwirkungen haben. Zumindest wird dadurch Ihr Debugger vermasselt (wenn Sie Ihren Code debuggen und eine Überwachung für diese Variable hinzufügen, wird die Eigenschaft zu beliebigen Zeiten ausgewertet, wodurch sich Ihr Verhalten ändert). Also, wenn Sie dies zu einer Eigenschaft machen, brechen Sie Ihren Code auf "interessante" Weise. ;-) –

1

können Sie Nullable-Typen verwenden und die Null-Koaleszenz-Operator eine Size Eigenschaft zu deklarieren:

Size? _containerSize; 

Size ContainerSize { 
    get { 
    return (_containerSize ?? (_containerSize = _InitialContainerSize)).Value; 
    } 
} 

Sie können es dann wie folgt verwenden:

void PerformLayout() { 
    var size = ContainerSize; 
    // ... 
} 

Wenn der Typ Sie zu faul initialisieren Ist ein Referenztyp, wird es noch einfacher.

Eine weitere Option ist die Verwendung des Typs Lazy<T>. Dies kann in Multi-Threading-Szenarien verwendet werden, in denen der obige Code brechen kann:

Lazy<Size> _containerSize = new Lazy<Size>(() => _InitialContainerSize); 

void PerformLayout() { 
    var size = _containerSize.Value; 
    // ... 
} 
1

Es gibt viele Möglichkeiten, dies zu erreichen. Sie können eine komplexe Zustandsmaschine erstellen, die Ihre Logik ausführt (am schnellsten), aber in vielen Fällen wird das Overkill sein. Alternativ können Sie einen Booleschen Überblick behalten, der den Zustand Ihrer Instanz genau so enthält, wie Sie ihn jetzt haben. Sie können auch beiden Lösungen in eine einfache Zustandsmaschine mit Methoden wie (moderatly schnell) zu kombinieren entscheiden:

public class TestClass 
{ 
    private Action performLayoutAction; 

    public TestClass() 
    { 
     // initial state 
     performLayoutAction = InitializePeformLayout; 
    } 

    public void PerformLayout() 
    { 
     performLayoutAction(); 
    } 

    private void InitializePeformLayout() 
    { 
     // whatever 

     performLayoutAction = ContiniousPerformLayout; 
    } 

    private void ContiniousPerformLayout() 
    { 
     // whatever 
    } 
} 
Verwandte Themen