Le bout de code ci-dessous montre une utilisation conceptuelle des WeakReference. L’idée des références faibles étant qu’elles n’empêchent pas la collection par le GC, mais que si jamais le GC n’est pas passé, elles permettent de retrouver une “vraie” référence sur l’objet.
Ceci est intéressant dans le cas d’objets lourds, utilisés peu fréquemment et qui ne sont pas trop compliqués à reconstruire. Ca permet de ne pas bloquer la mémoire, mais si jamais ça ne gêne pas, on évite de tout reconstruire, ce qui est appréciable.
using System; namespace TestWeakReferenceIsAlive { class Program { static void Main(string[] args) { WeakReference ReferenceFaible = null; // Juste pour créer une portée à la sortie de laquelle // on perdra la référence forte sur l'objet instancié if (true) { var ReferenceForte = new { Nom = "Gouigoux" }; ReferenceFaible = new WeakReference(ReferenceForte); } // ... // Pendant ce temps, le GC peut décider de collecter ou pas l'objet instancié, // rendant possible ou pas une récupération de l'objet par sa référence faible // ... if (ReferenceFaible.IsAlive) { // Dangereux, car la mémoire correspondant à l'objet pourrait très bien être // recyclée entre le moment où on a fait le IsAlive et celui où on récupère // une référence forte ci-dessous dynamic ReferenceForte = ReferenceFaible.Target; if (ReferenceForte != null) { // C'est pourquoi il faut tester ici la nullité // pour être sûr qu'on a bien récupérer l'objet Console.WriteLine(ReferenceForte.Nom); } } else { Console.WriteLine("Trop tard, il faut réinstancier Personne"); } } } }
Ce que je ne comprends pas, c’est à quoi sert le IsAlive ? De toute façon, on n’a pas de garantie qu’entre le moment où on teste si l’objet est vivant et celui où on récupère une référence forte dessus, il ne disparaitra pas. Et donc, nous sommes obligés quoi qu’il arrive de vérifier que la référence retrouvée n’est pas nulle.
Alors quel est l’utilité de IsAlive ? Juste savoir si l’objet est encore disponible ? Oui, mais pourquoi donc aurait-on besoin de cette information pour autre chose que pour le récupérer après ???
Toutes les idées / commentaires sont les bienvenus…
[Edit]
Justement, un commentaire de JB Evain que je recopie tel quel (il n’apparait pas en commentaire, car je n’ai migré que le contenu depuis mon ancien hébergeur, désolé) :
En fait elle est uniquement utile dans le cas où elle retourne False. Donc dans un scénario où on dit:
if (!weakRef.IsAlive) {
// repopulate cache.
}L’intention du code est un peu plus claire qu’en écrivant:
if (weakRef.Target == null) {
// repopulate cache
}Dans le cas où on est intéressé par la valeur, le plus simple est de ne pas s’en soucier du tout, et d’utiliser directement sa .Target en validant qu’elle n’est pas null
Pour une fois la MSDN est précise là dessus d’ailleurs.
[Edit – Août 2012]
Dans la version 4.5 de .NET qui arrive avec Visual Studio 2012, il y a désormais une version fortement typée WeakReference<T>, qui ne présente plus la méthode IsAlive, mais seulement TryGetTarget.
Plus d’infos sur http://msdn.microsoft.com/en-us/library/gg712738(v=vs.110).