我可以创建一个列表<弱引用>吗?

本文关键字:引用 列表 创建 一个 我可以 | 更新日期: 2023-09-27 18:33:18

我正在尝试使用 4.5 泛型实现创建一个WeakReference列表,以便我可以避免类型检查和WeakReference目标的强制转换。 但是,WeakReference<T>似乎不支持协方差,所以我正在尝试建立一种解决方法。

我认为这应该是可行的,因为每个 T 都是特定继承链中的一种类型。 所以,我的想法是这样的:

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()));

我尝试为 WeakReference 创建一个包装类(因为它是不可继承的),但这不起作用。 无论如何,该列表将不接受除WeakReference<Animal>以外的任何键入WeakReference

我可以创建自己的泛型WeakReference实现,但这似乎违背了重点,因为我将在其中进行类型转换。 我找不到任何文档,但我假设框架版本可以更好地处理这个问题。

有没有另一种我没有想到的处理方法,或者我吠错了树?

我可以创建一个列表<弱引用<T>>吗?

WeakReference

不变的,因为它允许设置值,如果它是协变的,则无效。 要使其协变,您需要在引用周围创建一个只读包装器,并使用接口。

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);
        }
    }
}

转换的扩展方法也比较方便:

public static IReadOnlyWeakReference<T> AsReadOnly<T>(
    this WeakReference<T> reference)
    where T : class
{
    return new WeakReferenceWrapper<T>(reference);
}

现在我们可以写:

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());
你可以

简单地使用WeakReference<Animal>本身,无论如何列表是List<WeakReference<Animal>>类型,所以即使有协方差,你也无法访问更多的派生成员。

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()));

或者,如果您更喜欢保留更具体的类型,有一种方法。我之前已经用访客模式解决了它。看看这是否有帮助。

我的建议是创建一个弱引用(列表)列表,并将其公开为IEnumerable,如下所示:

private List<WeakReference> innerList = new List<WeakReference>();
public IEnumerable<T> List
{
    get
    {
        return (this.innerList.Where(x => x.Target is T).Select(x => (T) x.Target));
    }
}