【问题标题】:Calling a generic function in VB.NET / C#在 VB.NET / C# 中调用泛型函数
【发布时间】:2010-06-02 12:30:04
【问题描述】:

问题:我想调用一个泛型函数,定义为:

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

现在当我调用它时,我想使用以下任何变体:

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

但它不起作用。 我觉得必须输入非常烦人和不可读

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

有没有办法通过从实例中获取类型来调用泛型函数?

【问题讨论】:

    标签: c# .net asp.net vb.net generics


    【解决方案1】:

    在我看来,您想为您的 XMLserialization.cConfiguration 类型创建一个较短的别名。尝试使用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)()
    

    【讨论】:

      【解决方案2】:

      泛型和反射是非常可怜的朋友。但是,您可以通过MakeGenericMethod 执行此操作。然而,这将是困难和丑陋的。

      由于XmlSerializer 是基于Type 实例 - 我会颠倒一些事情:让真正 代码基于Type,并从浅泛型版本调用它; C# 中的示例:

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

      【讨论】:

        【解决方案3】:

        仅使用 System.Reflection 命名空间的方法,这对于您试图节省的努力真的不值得。

        【讨论】:

          【解决方案4】:

          泛型方法的类型是在编译时确定的,这就是为什么不能使用变量来设置它的原因。这是泛型编程和类型反射之间的关键区别。

          【讨论】:

            【解决方案5】:

            有一个很好的理由说明为什么你不能在代码中轻松地做到这一点,以及为什么反射是这么多额外的工作:泛型都是关于保留类型的,所以你可以使用 List(Of Integer) 而不是 List(Of Object) 并拥有对所有内容进行强制转换/装箱,并且它们通过在代码中保持强类型化来提高代码的可维护性(因此您可以获得更少的运行时强制转换和类型异常)。

            泛型实际上是编译时的。它们允许您延迟指定的类型,以便您的泛型代码可以重复使用或具有由另一个程序集指定的类型。

            但是您的反序列化是运行时的 - 您在编写代码时不知道您将拥有什么类型,这就是为什么您需要一个变量来保存该类型。在这种情况下,使用通用代码并没有真正的好处——您的序列化成本将比装箱成本高几个数量级,并且对于强类型结果没有代码可维护性好处,因为您仍然不知道是什么它在编译时。

            简而言之,这很难是 .Net 告诉您检查初始假设的方式 - 将您的方法更改为:

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

            然后将您的结果从对象转换到您的 XMLserialization.cConfiguration 类。

            【讨论】:

              【解决方案6】:

              [这是按要求回答问题,不一定解决您更大的问题。]

              为避免需要 Of cConfiguration,您可以在泛型方法中包含被忽略的 ByVal Configuration As T

              那你可以说

              x = DeserializeFromXML(x)
              

              但@DanTao 的答案可能比我的要好,除非你找到Configuration 参数的用途。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2018-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多