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

我有一个泛型方法

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

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

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

我不断收到愚蠢的编译错误:

类型或命名空间名称“ t”可以 找不到(你是否遗漏了一个用途) 指令还是汇编引用?)

DoesEntityExist<MyType>(entityGuid, transaction);

可以很好地工作,但是我不想每次都使用 if 指令调用具有单独类型名称的方法。

166900 次浏览

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

可以调用的泛型方法的类型只有在执行时才知道,但是必须使用反射:

// 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 参数作为 type 参数传入,从而将 decision 向上推高一级吗?

如果你能告诉我们更多关于你在做什么的信息,那会很有帮助。有时您可能需要像上面那样使用反射,但是如果您选择了正确的点来做这件事,那么您可以确保您只需要做一次,并且让该点以下的所有内容以正常的方式使用 type 参数。

你不能用你描述的方式。关于泛型类型的要点是,尽管您在“编码时”可能不知道它们,但编译器需要能够在编译时解析它们。为什么?因为在内部,编译器将离开并为“开放”泛型类型的每个不同用法创建一个新类型(有时称为封闭泛型类型)。

换句话说,在编译之后,

DoesEntityExist<int>

是另一种类型的

DoesEntityExist<string>

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

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

另一个选择,正如其他答案中提到的,是使用反射从开放类型创建封闭类型,虽然这可能是建议在任何其他的极端利基场景我会说。

我不确定我是否正确理解了你的问题,但是你可以这样写你的代码:

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

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

DoesEntityExist(myTypeInstance, ...)

这样,您就不需要显式地编写类型,框架将自动从实例中取代该类型。

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

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);