2013-08-05 4 views
5

Hier ist ein Beispiel für eine Eigenschaft Ich habe, codiert so einfach wie möglichFaule Eigenschaft erfordern „this“

private IEnumerable<int> _blocks; 
private bool _blocksEvaluated; 
public IEnumerable<int> Blocks 
{ 
    get 
    { 
     if (!_blocksEvaluated) 
     { 
      _blocksEvaluated = true; 
      _blocks = this.CalculateBlocks(0).FirstOrDefault(); 
     } 
     return _blocks; 
    } 
} 

Dies ist die ausführliche; Ich möchte es, wenn möglich, präziser machen. Folgendes wäre akzeptabel ...

private Lazy<IEnumerable<int>> _blocks = 
    new Lazy<IEnumerable<int>>(() => this.CalculateBlocks(0).FirstOrDefault()); 

... aber es kompiliert nicht.

Schlüsselwort 'this' ist in einer statischen Eigenschaft nicht gültig, statische Methode oder statische Feldinitialisierer

So kam ich mit den folgenden

struct MyLazy<TResult> 
{ 
    private bool evaluated; 
    private TResult result; 

    public TResult Evaluate(Func<TResult> func) 
    { 
     if (!evaluated) 
     { 
      evaluated = true; 
      result = func(); 
     } 
     return result; 
    } 
} 

private MyLazy<IEnumerable<int>> _blocks; 
public IEnumerable<int> Blocks 
{ 
    get { return _blocks.Evaluate(() => this.CalculateBlocks(0).FirstOrDefault()); } 
} 

Was ich am besten gefällt up, Aber gibt es einen besseren Weg?

Hinweis - Ich erkenne, dass veränderbare Strukturen in der Regel böse sind, aber sie scheinen wirklich nützlich für dieses spezielle Problem.

+0

Kann ich fragen, warum imenumerable, wenn Sie scheinen es nur 1 einzigen Wert zuweisen? – terrybozzio

+0

'CalculateBlocks' gibt einen 'IEnumerable >' –

Antwort

6

Initialisieren Sie einfach Ihr Feld im Konstruktor.

public class MyClass 
{ 
    public MyClass() 
    { 
     _blocks = new Lazy<IEnumerable<int>>(() => this.CalculateBlocks(0).FirstOrDefault()); 
    } 

    private readonly Lazy<IEnumerable<int>> _blocks; 
} 
+0

zurück Das ist natürlich richtig. Leider ärgert mich jetzt [dieses Problem] (http://stackoverflow.com/q/4460206/644812) wirklich, also könnte ich meine benutzerdefinierte Struktur sowieso einfach verwenden. –

4

Sie können nicht this verwenden, wenn eine Instanz Feld zu initialisieren, aber man kann es im Konstruktor einfach initialisieren, das zu adressieren.

private Lazy<IEnumerable<int>> _blocks; 

public MyClass() 
{ 
    _blocks = new Lazy<IEnumerable<int>>(
     () => this.CalculateBlocks(0).FirstOrDefault()); 
} 

public IEnumerable<int> Blocks 
{ 
    get 
    { 
     return _blocks.Value; 
    } 
}