同时使用值和引用类型的泛型的协方差解决方法

Covariance workaround for generic using both value and reference types

前言:我知道协方差目前不适用于值类型 (c.f。[1], [2])。


我有一个泛型可以简化如下:

public interface IDynamicValue<out T>
{
    T Get(Context context);
}
public abstract class DynamicValue<T> : IDynamicValue<T>
{
    public abstract T Get(Context context);
}

类型 T 在不同情况下被用作引用类型和值类型。

现在我 运行 遇到了如下情况:

public class SomeClass
{
    public object thing;

    public string ObjectToString(Context context)
    {
        if (thing is IDynamicValue<object>)
        {
            return (thing as IDynamicValue<object>).Get(context).ToString();
        }

        return thing.ToString();
    }
}

由于协变性,如果我将 DynamicValue<string> 作为对象传递,那么它将成功转换为 IDynamicValue<object> 并执行 Get 函数。

但是,如果我传递一个DynamicValue<int>,它不会被转换(如前所述,我明白为什么会这样),并且会返回o.ToString()

有什么变通方法可以让我在这种情况下对引用和键入 DynamicValues 的值执行 Get(context) 函数?如果可能,不使用反射的荣誉 :D

也许,你可以添加一个没有泛型的接口,并用它标记一些 类:

public interface IDynamicValue
{
    object Get(Context context);
}

public interface IDynamicValue<out T>
{
    T Get(Context context);
}

并检查:

public class SomeClass
{
    public object thing;

    public string ObjectToString(Context context)
    {
        if (thing is IDynamicValue<object>)
        {
            return (thing as IDynamicValue<object>).Get(context).ToString();
        }

        if (thing is IDynamicValue)
        {
            return (thing as IDynamicValue).Get(context).ToString();
        }

        return thing.ToString();
    }
}