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

     2023-03-11     105

关键词:

【中文标题】C#中的泛型,使用变量的类型作为参数[重复]【英文标题】:Generics in C#, using type of a variable as parameter [duplicate] 【发布时间】:2011-01-07 15:33:37 【问题描述】:

我有一个通用方法

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

我如何通过以下方式使用该方法:

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

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

类型或命名空间名称“t”可以 找不到(您是否缺少使用 指令还是程序集引用?)

DoesEntityExist<MyType>(entityGuid, transaction);

完美运行,但我不想每次都使用 if 指令来调用具有单独类型名称的方法。

【问题讨论】:

你不能那样使用泛型(第一个例子) 另外:为什么 DoesEntityExist() 方法需要事务参数? ***.com/questions/687363/… 和 ***.com/questions/2078914/c-dynamic-generic-type 的类似问题 @MitchWheat,也许他想检查该实体是否存在于数据库中。 这不是一个重复的问题。这是另一个问题的不同方面 - 另一个问题的答案不符合该问题的答案。 【参考方案1】:

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

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

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

伊克。

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

如果您能向我们提供有关您正在做的事情的更多信息,那将会有所帮助。有时你可能需要像上面那样使用反射,但是如果你选择了正确的点来做,你可以确保你只需要做一次,并且让低于该点的所有东西都以正常的方式使用类型参数。

【讨论】:

我认为这个答案中最重要的是ick。那和编译时类型安全. @Mitch:问题在于有时这是必要的。它很丑陋,应该尽可能避免......但偶尔你需要它。 @JonSkeet: 有没有办法使用dynamic 关键字来适应这种情况? @MoslemBenDhaou:不,因为这里没有用于类型推断的实例。 @MoslemBenDhaou:你可以通过一个中间泛型方法使用dynamic 来推断类型。如果这还不够信息,请提出一个新问题 - 它与这个问题有很大不同,因此在 cmets 中追求它并不理想。【参考方案2】:

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

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

【讨论】:

这太棒了!有什么缺点吗?似乎比使用反射更优雅地解决原始问题?? 只有在声明类型足够的情况下才有效。如果实体被声明为对象怎么办? JonSkeet 的解决方案创建了泛型版本,其中 T 是真实类型,而不是声明的类型。 我不知道使用T约束可以让你在调用方法时绕过类型参数。当我可以做Sort(input)时,我试图找出类似Sort&lt;typeof(input)&gt;(input)的东西!【参考方案3】:

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

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

您可以通过以下方式调用该方法:

DoesEntityExist(myTypeInstance, ...)

这样你就不需要显式编写类型,框架会自动从实例中获取类型。

【讨论】:

【参考方案4】:

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

也就是说,编译后,

DoesEntityExist<int>

是不同的类型
DoesEntityExist<string>

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

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

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

【讨论】:

System.Enum 作为具有约束的泛型类型参数[重复]

】System.Enum作为具有约束的泛型类型参数[重复]【英文标题】:System.Enumasagenerictypeparameterwithconstraints[duplicate]【发布时间】:2012-09-2405:40:08【问题描述】:可能重复:CreateGenericmethodconstrainingTtoanEnumEnumtypeconstraintsinC#考虑以下类:pu... 查看详情

c#中的泛型和泛型集合

...性能,他的最常见应用就是创建集合类,可以约束集合类中的元素类型。比较典型的泛型集合是List<T>和Dictionary<>;泛型集合List<T>语法List<T>对象名=newList<T> 查看详情

详解c#泛型(代码片段)

  一、C#中的泛型引入了类型参数的概念,类似于C++中的模板,类型参数可以使类型或方法中的一个或多个类型的指定推迟到实例化或调用时,使用泛型可以更大程度的重用代码、保护类型安全性并提高性能;可以创建自定义... 查看详情

在 C# 中使用枚举作为泛型类型参数 [重复]

】在C#中使用枚举作为泛型类型参数[重复]【英文标题】:UsingenumasgenerictypeparameterinC#[duplicate]【发布时间】:2011-06-2210:27:37【问题描述】:可能重复:EnumtypeconstraintsinC#是否可以通过使用其包装类Enum将enum类型用作泛型参数?我有... 查看详情

java中的泛型理解(代码片段)

...义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。泛型的本质是为了参数化类型(在不创建新的类... 查看详情

c#中的泛型是啥意思?

泛型是2.0版C#语言和公共语言运行库(CLR)中的一个新功能。泛型将类型参数的概念引入.NETFramework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时... 查看详情

关于ts的泛型

1.泛型是什么泛型,顾名思义,就是可以适用于多个类型,使用类型变量比如T帮助我们捕获传入的类型,之后我们就可以继续使用这个类型。如下定义了一个identity泛型函数,<T>添加了类型变量T,它就可以帮助捕获我们传入... 查看详情

在 C# 中生成类,该类继承使用 Telosys 代码生成工具使用类型参数的泛型类

...生成类,该类继承使用Telosys代码生成工具使用类型参数的泛型类【英文标题】:GeneratingClassinc#thatinheritsagenericclasswhichusestypeparameterusingTelosyscodegenerationtool【发布时间】:2022-01-0214:57:29【问题描述】:我需要为我的Country实体生成C... 查看详情

java的泛型使用(代码片段)

...;就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式,然后再使用时传入具体的类型。举个例子:ArrayList<String>strList=newArrayList<String>();ArrayList<Integer>intLi... 查看详情

java的泛型使用(代码片段)

...;就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式,然后再使用时传入具体的类型。举个例子:ArrayList<String>strList=newArrayList<String>();ArrayList<Integer>intLi... 查看详情

多类型参数约束的C#泛型语法[重复]

...Genericmethodsandmultipleconstraints我需要一个具有两个类型约束的泛型函数,每个约束都继承自不同的基类。我知道如何用一种类型做到这一点:voidfoo< 查看详情

c++模板(代码片段)

...类型别名时将类型或参数作为参数  指C++程序设计语言中的函数模板与类模板,是一种参数化类型机制,大体对应于java和C#中的泛型,但也有一些功能上的显著差异(C++模板支持后两者没有明确对应的模板模板参数和模板非... 查看详情

c#中的泛型

...解一下泛型的定义:泛型允许我们延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。(也就是说泛型是可以与任何数据类型一起工作的类或方法)模块内高内聚,模块间低... 查看详情

如何从 C# 中的泛型类型数组中选择一组随机值?

】如何从C#中的泛型类型数组中选择一组随机值?【英文标题】:HowtopicksetnumberofrandomvaluesfromagenerictypearrayinC#?【发布时间】:2020-05-2208:38:18【问题描述】:我想从泛型类型数组中选择一组随机值(比如说2个值)。我设法实现了... 查看详情

java中的泛型

泛型的概念泛型:  泛型是一种末知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型  泛型也可以看成是一个变量用来接收数据类型  Ee:Element元素  Tt:Type类型是否使用泛型的对比不使用泛型/***... 查看详情

c#中的泛型

前言这篇文章和大家一起学习泛型。我们目前使用的语言结构,可以建立多种不同类型的强大对象。具体步骤是声明类,封装需要的行为之后创建类的实例对象。目前为止,所有类声明用到的类型都是特定类型。有可... 查看详情

java基础——java中的泛型(值得一看)

Java中的泛型泛型的概念所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值以及参数类型。这个类型参数将在使用时(利用继承或实现这个接口,用这个类型声明变... 查看详情

java的泛型使用(代码片段)

...;就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式,然后再使用时传入具体的类型。举个例子:ArrayList<String>strList=newArrayLi 查看详情