简体   繁体   English

在VB.NET / C#中调用泛型函数

[英]Calling a generic function in VB.NET / C#

Question: I want to call a generic function, defined as: 问题:我想调用泛型函数,定义如下:

      Public Shared Function DeserializeFromXML(Of T)(Optional ByRef strFileNameAndPath As String = Nothing) As T

Now when I call it, I wanted to do it with any of the variants below: 现在,当我打电话给它时,我想用下面的任何变体来做:

Dim x As New XMLserialization.cConfiguration
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of x)()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(GetType(x))()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of GetType(x))()

But it doesn't work. 但它不起作用。 I find it very annoying and unreadable having to type 我发现打字非常烦人且不可读

    x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of XMLserialization.cConfiguration)()

Is there a way to call a generic function by getting the type from the instance ? 有没有办法通过从实例中获取类型来调用泛型函数?

Generics and reflection make very poor friends. 泛化和反思使非常可怜的朋友。 However, you can do this via MakeGenericMethod . 但是,您可以通过MakeGenericMethod执行此操作。 However, that is going to be hard and ugly. 然而,这将是艰难和丑陋的。

Since XmlSerializer is based around Type instance - I would reverse things: have the realy code Type based, and call into that from the shallow generic version; 由于XmlSerializer基于Type实例 - 我会反转的东西:有基于Type真实代码,并从浅泛型版本调用它; example in C#: C#中的示例:

public T DeserializeFromXML<T>(string path) {
   return (T)DeserializeFromXML(typeof(T), path);
}
public object DeserializeFromXML(Type type, string path) {
    //TODO: real code
}

仅使用System.Reflection命名空间的方法,这对于您尝试保存的工作确实不值得。

It sounds to me like you want to create a shorter alias for your XMLserialization.cConfiguration type. 听起来我想为你的XMLserialization.cConfiguration类型创建一个更短的别名。 Try using the Imports statement to accomplish this: 尝试使用Imports语句来完成此任务:

' at the top of the file
Imports C = XMLserialization.cConfiguration

' somewhere in the body of the file
Dim x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of C)()

There's a good reason why you can't do this easily in code and why the reflection is so much extra work: generics are all about preserving type, so you can have a List(Of Integer) instead of a List(Of Object) and have to cast/box everything, and they improve code-maintainability by maintaining strong typing through the code (so you get fewer run-time cast and type exceptions). 有一个很好的理由说明为什么你不能在代码中轻松地做到这一点以及为什么反射是如此多的额外工作:泛型都是关于保留类型,所以你可以有一个List(Of Integer)而不是List(Of Object)和必须转换/包装所有内容,并通过代码维护强类型来提高代码可维护性(这样可以减少运行时转换和类型异常)。

Generics are really compile-time. 泛型是真正的编译时间。 They let you defer the type being specified so that your generic code can be re-used or have the type specified by another assembly. 它们允许您推迟指定的类型,以便可以重用通用代码或具有另一个程序集指定的类型。

However your deserialisation is run time - you don't know what type you'll have when you're writing the code, which is why you need a variable to hold the type. 然而,你的反序列化是运行时 - 你不知道在编写代码时你将拥有什么类型,这就是你需要一个变量来保存类型的原因。 In this case there isn't really any benefit to having the generic code - your serialisation costs will be orders of magnitude greater than the boxing cost, and there's no code-maintainability benefit for the strongly typed result as you still don't know what it is at compile-time. 在这种情况下,拥有通用代码并没有任何好处 - 您的序列化成本将高于装箱成本的数量级,并且对于强类型结果没有代码可维护性优势,因为您仍然不知道什么它是在编译时。

In short, this being hard is .Net's way of telling you to review your initial assumptions - change your method to: 简而言之,这很难实现.Net的方式告诉您检查您的初始假设 - 将您的方法更改为:

Public Shared Function DeserializeFromXML(Optional ByRef strFileNameAndPath As String = Nothing) As Object

And then cast your result from object to your XMLserialization.cConfiguration class. 然后将结果从object转换为XMLserialization.cConfiguration类。

The type of a generic method is determined at compile time, which is why you can't set it using a variable. 泛型方法的类型是在编译时确定的,这就是您无法使用变量进行设置的原因。 This is a key difference between generic programming and type reflection. 这是泛型编程和类型反射之间的关键区别。

[This is answering the question as asked, not necessarily solving your bigger issue.] [这是回答问题,不一定解决你的更大问题。]

To avoid the Of cConfiguration being required you could include an ignored ByVal Configuration As T in the generic method. 要避免使用Of cConfiguration ,可以在泛型方法中包含忽略的ByVal Configuration As T

Then you could say 然后你可以说

x = DeserializeFromXML(x)

But @DanTao's answer is probably better than mine unless you find a use for the Configuration parameter. 但是@DanTao的回答可能比我的好,除非你找到了Configuration参数的用法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM