如何进行可空类型约束?

时间:2010-10-07 03:49:20

标签: c#

假设我有以下愿望,以简化IConvertible以允许我通过使用泛型类型参数来调用它们。我计划通过创建泛型Converter并将它们存储在静态泛型类的静态属性上来实现。以下是生成委托::

的代码
static class IConvertibleHelper<T> where T : struct, IConvertible
{
    public static readonly Converter<IConvertible, T> Converter;
    public static readonly Converter<IConvertible, T?> NullableConverter;
    static IConvertibleHelper()
    {
        Type type = typeof(T).IsEnum ? Enum.GetUnderlyingType(typeof(T)) : typeof(T);
        Converter = Delegate.CreateDelegate(typeof(Converter<IConvertible, T>), typeof(Convert).GetMethod("To" + type.Name,new Type[]{typeof(object)})) as Converter<IConvertible, T>;
        NullableConverter = obj => obj == null ? default(T?) : (T?)Converter(obj);
    }
}

顺便说一句,添加对Enum的支持有一个小的副作用,因为它们从IConvertible继承而且显然从UnderylingType到Enum的转换是隐式的,因此只需要委托的返回类型。

现在,困难的部分已经完成,我想添加我的扩展方法:

 public static class IConvertibleHelper
 {
   public static T To<T>(this IConvertible convertible) where T:struct,IConvertible
   {
    return IConvertibleHelper<T>.Converter(convertible);
   }
   public static T? To<T?>(this IConvertible convertible) where T : struct, IConvertible
   {
      return IConvertibleHelper<T>.NullableConverter(convertible);
   }
 }

第一种扩展方法很好,甚至可以工作! 第二个扩展根本不编译。我可以使用以下相当蹩脚的工作:

 public static T? ToNullable<T>(this IConvertible convertible) where T : struct, IConvertible
 {
  return IConvertibleHelper<T>.NullableConverter(convertible);
 }

但后来我们不得不要求调用不同的签名来转换为可以为空的值类型。 更糟糕的解决方法(出于可用性原因,imo),是使用out或ref参数进行返回,并使用两种方法。这在技术上允许类型推理魔术发生,但是调用这个简单的小扩展方法更加烦人。

2 个答案:

答案 0 :(得分:0)

很抱歉,您不允许在尖括号内使用可以为空的类型,但这是不允许的。我知道这很蹩脚,但它今天的编译工作方式。你不能在那里放置一个具体的可空类型,例如“bool?”

这要求您更改方法名称或添加一些参数。对不起我知道这不是你在哪里跳,但它不容易绕过编译器本身。因此,您的ToNullable解决方案与任何解决方案一样好。

答案 1 :(得分:0)

您的ToNullable<T>解决方法是您最接近的。即使 是您想要的语法,也不允许方法签名 仅因通用约束而不同。