9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[C#][.NET 4.5~] WeakReference<T>/弱参照の使い方

Last updated at Posted at 2016-12-23

C# で弱参照を使用したい場合の方法メモ

目的

  • インスタンスへの参照は保持したいが、強い参照を持ってGCの回収対象にならないのを避けたい
  • 循環参照の回避
  • コンポジションしている子のインスタンスから親のインスタンスを参照したい場合
    • => ただもし、ViewModel => Viewの操作で考えてるなら、Messenger パターン使ったほうが良い

使い方

初期化
var wref = new WeakReference<Hoge>(new Hoge);
参照時
Hoge obj;
if (wref.TryGetTarget(out obj))
{
    // 参照が必要な処理
}

WeakReference<T>.TryGetTarget(out obj) は取得成功/失敗をboolean型で返す。
注意点として、強い参照の保持期間は当然ながら、if式の間だけではなく、上記の例でいうと取得後、obj が破棄されるまでになる。一時変数ではなく、長い生存期間をもつ変数が束縛してしまうと弱参照で持った意味がなくなる。

メモ

WeakReference<T> は、.NET Framework 4.5 以降で使用可能。
それ以前は WeakReference がつかえたが、書き方によってはGCで回収された後に参照できる方法がとれてしまった。
そこらへんは以下の記事が詳しい。

WeakReference・WeakReference の違いと、そこに潜む罠 - Qiita

WeakReference<T> は、TryGetTarget の文法上、使用中は強い参照を持つことが強制されるため上記の問題は解決された。

どうやって実現されているか

TODO: WeakReference<T> は内部的に IntPtr で持っているとかなんとかの記事を見かけたことがあるけれども、その記事が見当たらないのと正確かどうかがわからないので追記する

C# 7.0から

出力変数宣言

C# 7 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C

C# 7.0 からは、新しい文法として出力変数宣言が使えるため、書き方が簡略化できるようです。

C#7.0からの書き方
if (wref.TryGetTarget(out var obj))
{
    // 参照が必要な処理
}

参考

WeakReference(T) クラス (System)
【雑記】弱参照 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
【.NET】弱いつながりでWeakReference | 創造的プログラミングと粘土細工

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?