我有一个通用的方法与此签名:测试泛型方法的参数是一个类
private void MyGenericMethod<T>(T arg) where T : class
{}
如果我通过,也就是说,这种方法的一个整数,我得到一个ArgumentException,传递的值不匹配限制。这很好,但是我怎样才能预先确定我所传递的内容将与“类”约束相匹配,以便不抛出异常?
我有一个通用的方法与此签名:测试泛型方法的参数是一个类
private void MyGenericMethod<T>(T arg) where T : class
{}
如果我通过,也就是说,这种方法的一个整数,我得到一个ArgumentException,传递的值不匹配限制。这很好,但是我怎样才能预先确定我所传递的内容将与“类”约束相匹配,以便不抛出异常?
编译器将已经为你做 - 你应该真正看到:
类型“诠释”必须是为了在泛型类型或方法来使用它作为参数“T”引用类型'blah.MyGenericMethod(T)'
在编译时。
棘手的情况是:在非专利药仿制药时
where T : class
很多。有时,最好是使用运行时间验证针对T
MakeGenericMethod
等) - 再次,只是检查在运行时另外,还要注意where T : class
并不实际上意味着T
是一类 - 这意味着它是一个引用类型,可以包含接口和代理。同样,where T : struct
实际上并不意味着T
是struct
- 这意味着它是一个不是Nullable<>
的结构。
+1很好的解释。 – 2011-06-03 08:57:46
是的,这正是发生的情况,但我想避免产生的成千上万的抛出和捕获的异常。我实际调用与MakeGenericMethod的方法,但传递的类型是动态的(在一个循环中),我希望打电话来避免异常的方法之前,把一个简单的,如果英寸 – Craig 2011-06-03 09:01:43
@Craig你从来没有提到过MakeGenericMethod; p只需检查类型 - '!type.IsValueType'可能已经够用了,或者'type.IsClass || type.IsInfaceface' – 2011-06-03 09:11:44
你实际得到的编译错误,如果传递的参数不是引用类型。但是,如果您填入值类型,则可以避开该类型,但这是一种有效的引用类型。
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
也符合真正的在它的层次结构(基础/派生类)的类型,而检查GetType
对typeof
在这一水平只需要类型:
int i = 0;
bool b = i is object;
b = i.GetType() == typeof(object);
显然,在你的情况你赢了”我想扔一个ArgumentException
,也许什么都不做。
删除where子句并用'is'运算符检查方法内部? (http://msdn.microsoft.com/en-us/library/scekt9xw(v=VS.100).aspx) – Kevin 2011-06-03 08:41:45
编译器为你做这个,你的更广泛的情况是编译器无法捕捉到你的案件? – 2011-06-03 08:50:15
如果您不知道您传递的内容是否有效,是否可以不尝试/捕获异常?我同意亚当,虽然看到你为什么不知道你通过什么可能是回答你的问题的关键。 – Chris 2011-06-03 08:51:59