I'm trying to create a List of WeakReference
s using the 4.5 generic implementation so that I can avoid type checking and casting of the WeakReference
target. But, WeakReference<T>
doesn't appear to support covariance, so I'm trying to establish a workaround.
I'm thinking it should be doable since each T would be of a type in a particular inheritance chain. So, what I'm thinking would be along these lines:
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 WeakReference (since it's non-inheritable), but that doesn't work. No matter what, the list won't accept any typed WeakReference
other than WeakReference<Animal>
.
I could create my own generic WeakReference
implementation, but that would seem to be defeating the point since I'd be doing type casting within it. I can't find any documentation, but I'm kind of assuming the framework version handles this better.
Is there another way of handling this that I'm not thinking of, or am I barking up the wrong tree?
WeakReference
is invariant, since it allows the value to be set, and that wouldn't be valid if it were covariant. To make it covariant you'll need to make a read only wrapper around the reference, 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);
}
}
}
An extension method for the conversion is also somewhat convenient:
public static IReadOnlyWeakReference<T> AsReadOnly<T>(
this WeakReference<T> reference)
where T : class
{
return new WeakReferenceWrapper<T>(reference);
}
Now we can 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());
You could simply use WeakReference<Animal>
itself, anyways list is of type List<WeakReference<Animal>>
, so you even with the covariance, you'll not be able to access the 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 prefer to keep the more specific type, there is a way. I've solved it earlier with visitor pattern. See if that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With