2011-10-06 115 views
6

我正在试验流利的扩展方法。使用通用约束与值类型

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

 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>()给出了错误“类型'System.DateTime'必须是引用类型才能在通用类型或方法中用作参数'T'.... As(object)” 。从错误消息我看到它是解决使用上面的方法,因为它是需要引用类型。

+0

什么的C#版本使用你正在用吗?在.NET 4中,选择了第二个重载。 –

+1

你的意思是像'object o = 42; var i = o.As ();'给出语法错误?或者你能显示给出它的确切代码吗? – svick

+0

@ svick的评论让我想起了你可能试图用数据库结果做的事情,比如DataRow。如果是这样,则已经有一个扩展方法来将行中的对象值转换为适当的类型。 [.Field ](http://msdn.microsoft.com/en-us/library/bb360891.aspx) –

回答

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; 
+0

由于ValueType是 - 尽管它的名称 - 实际上是一个类的类型,后一个公式需要装箱论据。不幸的是,我真的不认为有什么办法可以让.net允许基于泛型参数的值类型重载。 – supercat