弱い参照

キャッシュみたいな。ずっと持ってるとリソース的に負荷が高いものは弱い参照が有効。

static readonly Dictionary<string, WeakReference> _cache
  =  new Dictionary<string, WeakReference>();

static object GetValue( string key ) {
  if ( !_cache.ContainsKey( key ) ) {
    _cache[key] = new WeakReference( new object );
  }

  var cacheValue = _cache[key].Target;
  if( cacheValue != null ) {
    return cacheValue;
  }

  var target = new object();
  _cache[key].Target = target;
  return target;
}

マルチスレッド環境においては WeakReference.IsAlive で判断はしないほうがいい。
いざ、Target を取得したときには false になっているかもしれないから。
ロックもできないしな。

ジェネリックで作ろうと思ったけど、初期化が固定されてないと出来ないことに気づいたんでやめた。


キーで初期化デリゲートよんでインスタンスもらってもいいけど。


と思いついたんで書いてみた。

public class Cache<TKey, TValue> {
  public delegate TValue InitializeDelegate( TKey key );
  readonly InitializeDelegate _initializeDelegate;

  public Cache( InitializeDelegate initializeDelegate ) {
    _initializeDelegate = initializeDelegate;
  }

  static readonly Dictionary<TKey, WeakReference> _cache
    = new Dictionary<TKey, WeakReference>();

  public TValue this[TKey key] {
    get {
      if ( !_cache.ContainsKey( key ) ) {
        _cache[key] = new WeakReference( _initializeDelegate( key ) );
      }

      TValue cacheValue = (TValue)_cache[key].Target;
      if (cacheValue.Equals( default( TValue ) )) {
        return cacheValue;
      }

      TValue target = _initializeDelegate( key );
      _cache[key].Target = target;
      return target;
    }
    set {
      _cache[key] = new WeakReference( value );
    }
  }
}

未検証。

こんなのとかも

public class Cache<TKey, TValue> where TValue : new() {
  public delegate TValue InitializeDelegate( TKey key );
  readonly InitializeDelegate _initializeDelegate;

  public Cache( InitializeDelegate initializeDelegate ) {
    _initializeDelegate = initializeDelegate;
  }

  public Cache() : this( delegate { return new TValue(); } ) {
  }

  以下略
}