2011-06-03 60 views
2

我有一个通用的方法与此签名:测试泛型方法的参数是一个类

private void MyGenericMethod<T>(T arg) where T : class 
{} 

如果我通过,也就是说,这种方法的一个整数,我得到一个ArgumentException,传递的值不匹配限制。这很好,但是我怎样才能预先确定我所传递的内容将与“类”约束相匹配,以便不抛出异常?

+1

删除where子句并用'is'运算符检查方法内部? (http://msdn.microsoft.com/en-us/library/scekt9xw(v=VS.100).aspx) – Kevin 2011-06-03 08:41:45

+3

编译器为你做这个,你的更广泛的情况是编译器无法捕捉到你的案件? – 2011-06-03 08:50:15

+0

如果您不知道您传递的内容是否有效,是否可以不尝试/捕获异常?我同意亚当,虽然看到你为什么不知道你通过什么可能是回答你的问题的关键。 – Chris 2011-06-03 08:51:59

回答

5

编译器将已经为你做 - 你应该真正看到:

类型“诠释”必须是为了在泛型类型或方法来使用它作为参数“T”引用类型'blah.MyGenericMethod(T)'

在编译时。

棘手的情况是:在非专利药仿制药时

  • 仿制药 - 所有这些类型的限制栈,所以你最终where T : class很多。有时,最好是使用运行时间验证针对T
  • 反射(MakeGenericMethod等) - 再次,只是检查在运行时

另外,还要注意where T : class并不实际上意味着T是一类 - 这意味着它是一个引用类型,可以包含接口和代理。同样,where T : struct实际上并不意味着Tstruct - 这意味着它是一个不是Nullable<>的结构。

+0

+1很好的解释。 – 2011-06-03 08:57:46

+0

是的,这正是发生的情况,但我想避免产生的成千上万的抛出和捕获的异常。我实际调用与MakeGenericMethod的方法,但传递的类型是动态的(在一个循环中),我希望打电话来避免异常的方法之前,把一个简单的,如果英寸 – Craig 2011-06-03 09:01:43

+1

@Craig你从来没有提到过MakeGenericMethod; p只需检查类型 - '!type.IsValueType'可能已经够用了,或者'type.IsClass || type.IsInfaceface' – 2011-06-03 09:11:44

1

你不可错过int,因为它是一个值类型和你有你的约束方法只接受引用类型。 如果你想支持任何那些你需要删除的泛型约束类似以下

private void MyGenericMethod<T>(T arg) 
     { 
      if(arg.GetType().IsValueType) 
      { 
       //T is value type 
      } 
     } 
+0

这与我想要的相反。我只想传递和处理引用类型。 – Craig 2011-06-03 09:02:12

+0

相同的逻辑将工作,请检查arg.GetType()。IsValueType,并相应地调用该方法。 – crypted 2011-06-03 10:41:58

0

你实际得到的编译错误,如果传递的参数不是引用类型。但是,如果您填入值类型,则可以避开该类型,但这是一种有效的引用类型。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication29 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int i = 0; 
      object o = (object)i; 
      MyMethod(o); 
      MyMethod(i); // Doesn't compile. 
     } 

     static void MyMethod<T>(T arg) where T : class 
     { 

     } 
    } 
} 

如果你是因为你在运行时做一些事情,如使用反射来调用该方法,否则你框的值类型收到此错误,那么你将只需要在使用前要检查参数:

static void MyMethod<T>(T arg) where T : class 
{ 
    if (arg is ValueType) 
     throw new ArgumentException(); 
} 

请注意,这将捕获所有值类型,无论它们是否装箱。还要注意的是使用is也符合真正的在它的层次结构(基础/派生类)的类型,而检查GetTypetypeof在这一水平只需要类型:

int i = 0; 
bool b = i is object; 
b = i.GetType() == typeof(object); 

显然,在你的情况你赢了”我想扔一个ArgumentException,也许什么都不做。

相关问题