C#中的泛型,使用变量类型作为参数

时间:2010-01-21 08:36:14

标签: c# .net generics types

我有一个通用的方法

bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;

如何以下列方式使用该方法:

Type t = entity.GetType();
DoesEntityExist<t>(entityGuid, transaction);

我一直收到愚蠢的编译错误:

  

类型或命名空间名称't'可以   找不到(你错过了使用   指令或程序集引用?)

DoesEntityExist<MyType>(entityGuid, transaction);

工作正常,但我不想每次都使用if指令调用带有单独类型名称的方法。

4 个答案:

答案 0 :(得分:155)

关于泛型的观点是给编译时类型安全 - 这意味着需要在编译时知道类型。

可以调用通用方法,其类型仅在执行时已知,但你必须使用反射:

// For non-public methods, you'll need to specify binding flags too
MethodInfo method = GetType().GetMethod("DoesEntityExist")
                             .MakeGenericMethod(new Type[] { t });
method.Invoke(this, new object[] { entityGuid, transaction });

伊克。

您是否可以将调用方法变为通用,并将类型参数作为类型参数传入,将决策推高到堆栈的上一级?

如果您可以向我们提供有关您正在做的事情的更多信息,那将有所帮助。有时您可能需要使用上面的反射,但是如果您选择正确的点来执行此操作,您可以确保只需要执行一次,并且让该点以下的所有内容以正常方式使用type参数。

答案 1 :(得分:32)

解决这个问题的一种方法是使用隐式转换:

bool DoesEntityExist<T>(T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;

这样称呼它:

DoesEntityExist(entity, entityGuid, transaction);

更进一步,你可以把它变成一个扩展方法(它需要在一个静态类中声明):

static bool DoesEntityExist<T>(this T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;

如此呼召:

entity.DoesEntityExist(entityGuid, transaction);

答案 2 :(得分:7)

我不确定我是否理解你的问题,但你可以用这种方式编写代码:

bool DoesEntityExist<T>(T instance, ....)

您可以按以下方式调用该方法:

DoesEntityExist(myTypeInstance, ...)

这种方式你不需要显式写入类型,框架会自动从实例中超越类型。

答案 3 :(得分:4)

您不能以您描述的方式使用它。关于泛型类型的观点是,虽然您可能在“编码时”不知道它们,但编译器需要能够在编译时解析它们。为什么?因为在引擎盖下,编译器将消失并为“开放”泛型类型的每种不同用法创建一个新类型(有时称为封闭泛型类型)。

换句话说,在编译之后,

DoesEntityExist<int>

是与

不同的类型
DoesEntityExist<string>

这就是编译器能够实现编译时类型安全的方法。

对于您描述的场景,您应该将类​​型作为可在运行时检查的参数传递。

另一个选项,如其他答案中所提到的,是使用反射从开放类型创建封闭类型,尽管这可能是我所说的极端利基场景之外的其他任何建议。