我有一个带有此签名的通用方法:
private void MyGenericMethod<T>(T arg) where T : class
{}
如果我传递一个整数给这个方法,我得到一个ArgumentException,传递的值与限制不匹配。这很好,但我如何预先确定我传递的内容是否与“类”约束匹配,以便不抛出异常?
答案 0 :(得分:5)
编译器已经为你做了 - 你应该看到:
类型'int'必须是引用类型才能在泛型类型或方法'blah.MyGenericMethod(T)'
中将其用作参数'T'
在编译时。
棘手的情况是:
where T : class
很多 。有时最好对T
MakeGenericMethod
等) - 再次,只需在运行时检查另请注意,where T : class
实际上并不意味着T
是一个类 - 这意味着它是一个引用类型,可以包括接口和委托。同样,where T : struct
实际上并不意味着T
是struct
- 这意味着它是一个不是Nullable<>
的结构。
答案 1 :(得分:1)
您无法通过int
,因为它是值类型,并且您已将Method限制为仅接受引用类型。
如果你想支持任何你需要删除泛型约束的那些
private void MyGenericMethod<T>(T arg)
{
if(arg.GetType().IsValueType)
{
//T is value type
}
}
答案 2 :(得分: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
对于其层次结构中的类型(基类/派生类)也匹配true,而针对GetType
检查typeof
仅采用该级别的类型:
int i = 0;
bool b = i is object;
b = i.GetType() == typeof(object);
显然在你的情况下你不想抛出ArgumentException
,也许什么都不做。