对值类型使用泛型约束

本文关键字:泛型 约束 类型 | 更新日期: 2023-09-27 18:10:31

我正在试验流畅的扩展方法。

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

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

这工作得很好,但当我试图让它直观地使用重载的值类型

     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>()给出了错误"The type 'System "。DateTime'必须是一个引用类型,以便将其用作泛型类型或方法.... as (object)中的参数'T'。从错误消息中,我看到它正在解析使用上面的top方法,因为它是需要引用类型的方法。

对值类型使用泛型约束

在。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;