Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的泛型,使用变量类型作为参数_C#_.net_Generics_Types - Fatal编程技术网

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

C#中的泛型,使用变量类型作为参数,c#,.net,generics,types,C#,.net,Generics,Types,我有一个通用方法 bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable; bool-DoesEntityExist(Guid-Guid,ITransaction事务),其中T:IGloballyIdentifiable; 如何按以下方式使用该方法: Type t = entity.GetType(); DoesEntityExist<t>

我有一个通用方法

bool DoesEntityExist<T>(Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
bool-DoesEntityExist(Guid-Guid,ITransaction事务),其中T:IGloballyIdentifiable;
如何按以下方式使用该方法:

Type t = entity.GetType();
DoesEntityExist<t>(entityGuid, transaction);
Type t=entity.GetType();
DoesEntityExist(entityGuid,事务);
我一直收到愚蠢的编译错误:

无法找到类型或命名空间名称“t” 找不到(您是否缺少一个用户 指令或组件引用?)

DoesEntityExist(entityGuid,事务);

工作非常完美,但我不想每次都使用if指令以单独的类型名调用方法。

泛型的要点是提供编译时类型安全性,这意味着需要在编译时知道类型

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

// 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 });
哎呀

您是否可以将调用方法改为泛型,并将类型参数作为类型参数传入,从而将决策推到堆栈的更高级别


如果你能给我们更多关于你在做什么的信息,那会有帮助的。有时您可能需要如上所述使用反射,但如果您选择了正确的点来执行此操作,您可以确保只需要执行一次,并让该点下的所有内容都以正常方式使用类型参数。

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

也就是说,经过整理,

DoesEntityExist<int>
DoesEntityExist
是一种不同的类型

DoesEntityExist<string>
DoesEntityExist
这就是编译器如何实施编译时类型安全性

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


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

我不确定是否正确理解您的问题,但您可以用以下方式编写代码:

bool不存在(T实例,…)

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

DoesEntityExist(myTypeInstance, ...)

通过这种方式,您不需要显式地编写类型,框架将从实例中自动超越类型。

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

bool DoesEntityExist<T>(T entity, Guid guid, ITransaction transaction) where T : IGloballyIdentifiable;
更进一步,您可以将其转换为扩展方法(需要在静态类中声明):


您也不能这样使用泛型(第一个示例):为什么DoesEntityExist()方法需要事务参数?类似于和@Mitchheat的问题,他可能想检查数据库中是否存在该实体。这不是一个重复的问题。这是其他问题的一个不同方面——其他问题中的答案不符合这个问题的答案。我认为这个答案中最重要的是ick。这和编译时类型安全性有关。@Mitch:问题是有时它是必要的。这很难看,应该尽可能避免。。。但有时你也需要它。@JonSkeet:有没有办法使用
动态
关键字来调整它?@MoslemBenDhaou:没有,因为这里没有用于类型推断的实例。@MoslemBenDhaou:你可以通过中间泛型方法使用
动态
来推断类型。如果这还不够信息,问一个新问题-这与这个问题完全不同,在评论中追求它是不理想的。这太棒了!有什么缺点吗?对于原始问题,似乎比使用反射更优雅的解决方案??只有在声明的类型足够时,它才有效。若实体被声明为对象呢?JonSkeet的解决方案创建了一个泛型版本,其中T是实类型,而不是声明的类型。我不知道使用T约束可以在调用方法时绕过类型参数。当我可以做排序(输入)的时候,我正试图找出类似于排序(输入)的方法!
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);