使用值类型的通用约束

时间:2011-10-06 15:17:45

标签: c# generics extension-methods constraints fluent-interface

我正在尝试使用流畅的扩展方法。

我有以下简单的扩展方法来执行安全转换。

     public static T As<T>(this Object source)
         where T : class
     {
         return source as T;
     }

这很好用,但是当我试图直观地使用带有重载的valuetype时

     public static T As<T>(this ValueType source)
         where T : struct
     {
         return (T)source;
     }

我遇到了问题。方法解析逻辑总是选择上面的第一个方法,并给出结构不是类的语法错误(准确)。

有没有办法处理上述问题,或者我是否应该在同一方法中测试和处理所有类型时采用删除约束的路径?

====编辑:回答问题====

我正在针对3.5框架进行编译。我并不是真的想要完成任何事情;这只是上面的一个实验。我的兴趣被激发了,我把一些代码汇总在一起。

我并不特别担心它仍然是一个'安全'演员。这就是它的开始,并且可以使用default()保持安全 - 但这并不是问题和代码的重点,以确保“安全性”只是模糊不清。

至于表现力,value.As<int>()没有(int)value更具表现力;但为什么方法的用户必须“只知道”它只适用于引用类型?我尝试使用它更多的是关于方法的预期行为而不是表达性写作。

代码段value.As<DateTime>()给出错误“类型'System.DateTime'必须是引用类型才能在泛型类型或方法中将其用作参数'T'。As(宾语)”。从错误消息我看到它正在解决使用上面的top方法,因为它是需要引用类型的方法。

1 个答案:

答案 0 :(得分:3)

在.NET 4中,根据您的代码示例选择第二个重载。 (也是针对.NET 3.5进行测试,结果相同。)

int myInt = 1;
long myLong = myInt.As<long>(); // chooses ValueType version

然而,这只会让我们到达下一次崩溃的场景。 (T)source;导致无效的强制转换异常。您可以通过将方法编写为

来解决这个问题
public static T As<T>(this ValueType source)
    where T : struct
{
    return (T)Convert.ChangeType(source, typeof(T));
}

然而,我想知道你实际想要实现什么,因为我没有看到直接的好处。 (就此而言,这不像source as T对象版本那样安全。)例如,如何

long myLong = myInt.As<long>();

更具表现力或更易于使用
long myLong = (long)myInt;