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

Ger*_*orm 120 .net c# generics types

我有一个通用的方法

bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Run Code Online (Sandbox Code Playgroud)

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

Type t = entity.GetType();
DoesEntityExist<t>(entityGuid, transaction);
Run Code Online (Sandbox Code Playgroud)

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

找不到类型或命名空间名称't'(您是否缺少using指令或程序集引用?)

DoesEntityExist<MyType>(entityGuid, transaction);
Run Code Online (Sandbox Code Playgroud)

完美的工作,但我不想使用if指令每次调用具有单独类型名称的方法.

Jon*_*eet 161

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

可以使用仅在执行时已知的类型调用泛型方法,但您必须使用反射:

// 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 });
Run Code Online (Sandbox Code Playgroud)

伊克.

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

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

  • 我认为这个答案中最重要的是*ick*.那和*编译时类型安全*. (15认同)
  • @Mitch:麻烦的是*有时候*它是必要的.这很难看,应该尽可能避免......但有时你需要它. (9认同)
  • @MoslemBenDhaou:你可以通过一个使用`dynamic`来推断类型的中间泛型方法.如果这还不够,请提出一个新问题 - 这与在评论中追求它的这个问题有很大不同. (2认同)

小智 33

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

bool DoesEntityExist<T>(T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Run Code Online (Sandbox Code Playgroud)

这样称呼它:

DoesEntityExist(entity, entityGuid, transaction);
Run Code Online (Sandbox Code Playgroud)

更进一步,您可以将其转换为扩展方法(它需要在静态类中声明):

static bool DoesEntityExist<T>(this T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
Run Code Online (Sandbox Code Playgroud)

这样称呼:

entity.DoesEntityExist(entityGuid, transaction);
Run Code Online (Sandbox Code Playgroud)


小智 7

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

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

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

DoesEntityExist(myTypeInstance, ...)
Run Code Online (Sandbox Code Playgroud)

这种方式您不需要显式写入类型,框架将自动从实例中超过类型.


Rob*_*ine 5

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

也就是说,编译后,

DoesEntityExist<int>
Run Code Online (Sandbox Code Playgroud)

是不同的类型

DoesEntityExist<string>
Run Code Online (Sandbox Code Playgroud)

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

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

正如其他答案中提到的那样,另一种选择是使用反射从开放类型创建封闭类型,尽管在我所说的极端利基场景以外的任何情况下都可能建议这样做。