同时使用值和引用类型的泛型的协方差解决方法
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();
}
}
前言:我知道协方差目前不适用于值类型 (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();
}
}