Can I create a <WeakReference <T>> list?
I am trying to create a list WeakReference
using generic version 4.5 so that I can avoid type checking and target casting WeakReference
. But WeakReference<T>
doesn't seem to support covariance, so I'm trying to establish a workaround.
I think this should be doable as each T will have a type in a certain inheritance chain. So, I think it would be like this:
public class Animal { }
public class Tiger : Animal { }
public class Wolf : Animal { }
var mylist = new List<WeakReference<Animal>>();
mylist.Add(new WeakReference<Animal>(new Animal()));
mylist.Add(new WeakReference<Tiger>(new Tiger()));
mylist.Add(new WeakReference<Wolf>(new Wolf()));
I've tried creating a wrapper class for the WeakReference (since it doesn't inherit) but that doesn't work. No matter what the list will not accept any printed WeakReference
except WeakReference<Animal>
.
I could create my own generic implementation WeakReference
, but that would seem to defeat the point, since I will be doing type casting inside of it. I can't find any documentation, but my guess is that the framework version handles this better.
Is there another way to handle this that I don't think of, or am I barking the wrong tree?
source to share
WeakReference
is invariant since it allows a value to be set, and it is not valid if it were covariant. To make it covariant, you only need to create a readable wrapper around the link and also use an interface.
public interface IReadOnlyWeakReference<out T>
{
T Value { get; }
}
public class WeakReferenceWrapper<T> : IReadOnlyWeakReference<T>
where T : class
{
private WeakReference<T> reference;
public WeakReferenceWrapper(WeakReference<T> reference)
{
this.reference = reference;
}
public T Value
{
get
{
T output;
if (reference.TryGetTarget(out output))
return output;
else
return default(T);
}
}
}
The extension method for conversion is also somewhat convenient:
public static IReadOnlyWeakReference<T> AsReadOnly<T>(
this WeakReference<T> reference)
where T : class
{
return new WeakReferenceWrapper<T>(reference);
}
We can now write:
var mylist = new List<IReadOnlyWeakReference<Animal>>();
mylist.Add(new WeakReference<Animal>(new Animal()).AsReadOnly());
mylist.Add(new WeakReference<Tiger>(new Tiger()).AsReadOnly());
mylist.Add(new WeakReference<Wolf>(new Wolf()).AsReadOnly());
source to share
You can just use it WeakReference<Animal>
yourself, anyways list is of type List<WeakReference<Animal>>
, so even with covariance you won't be able to access more derived members.
var mylist = new List<WeakReference<Animal>>();
mylist.Add(new WeakReference<Animal>(new Animal()));
mylist.Add(new WeakReference<Animal>(new Tiger()));
mylist.Add(new WeakReference<Animal>(new Wolf()));
Or, if you'd rather keep a more specific type, there is a way. I solved this earlier with the visitor template. See if this helps .
source to share