Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.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
Vb.net 有没有一种方法可以在“T As IComparable(Of T)”上使用“>”操作符,而不是“a.GreaterThan(b)”,或者有没有一种方法可以简化我的包装行?_Vb.net_Generics_Icomparable - Fatal编程技术网

Vb.net 有没有一种方法可以在“T As IComparable(Of T)”上使用“>”操作符,而不是“a.GreaterThan(b)”,或者有没有一种方法可以简化我的包装行?

Vb.net 有没有一种方法可以在“T As IComparable(Of T)”上使用“>”操作符,而不是“a.GreaterThan(b)”,或者有没有一种方法可以简化我的包装行?,vb.net,generics,icomparable,Vb.net,Generics,Icomparable,考虑: MyClass(Of T As {New, IComparable(Of T)}) Sub MySub(a As T, b As T) If a.CompareTo(b) > 0 Then .... End If End Sub End Class 可通过定义以下内容使其更具可读性: Public Module MyModule <System.Runtime.CompilerServ

考虑:

MyClass(Of T As {New, IComparable(Of T)})

    Sub MySub(a As T, b As T)
        If a.CompareTo(b) > 0 Then
            ....
        End If
    End Sub
End Class
可通过定义以下内容使其更具可读性:

Public Module MyModule
        <System.Runtime.CompilerServices.Extension()> _
        Public Function GreaterThan(Of T As IComparable(Of T))(a As T, b As T) As Boolean
                Return (a.CompareTo(b) > 0)
        End Function
End Module
这是可以接受的,但作为更复杂表达式的一部分,能够定义运算符将是非常好的,因此可以说

    If a > b Then
但是,MyClass中的以下定义:

    Public Shared Operator >(a As T, b As T) As Boolean
        Return (a.CompareTo(b) > 0)
    End Operator
产生编译时错误此二进制运算符的至少一个参数必须为包含类型

有没有其他方法可以做到这一点

到目前为止,我有一个选择,但不是100%令人满意:

与此方法类似:

它为T创建一个包装器结构-一个包含单个字段的结构-然后在该包装器上定义运算符。这样就可以编写如下代码:

Public Sub MySub(valueT As T)
    Dim value As New Num(Of T, TNum)(valueT)
    If value > Me.MaxElement Then
        ...
    End If
End Sub
但是必须将Num-Dim value中的一个值包装为新的NumOf T,TNumvalueT,以便获得要编译的>并不比执行我已经完成的工作更方便:

Public Sub MySub(valueT As T)
     If valueT.GreaterThan(Me.MaxElement) Then
        ...
    End If
End Sub
因此,另一种解决方案是通过某种方式使这条线路更加优雅:

使Num工作所涉及的类型受上述参考和此方法的启发:

指本文件中的Policy.I.cs和Policy.INumeric.cs:

以下是关键类型的简化草图:

Public Interface INumeric(Of T As {New, IComparable(Of T)})
        Function Zero() As T
        ...
        Function Add(a As T, b As T) As T
        ...
        Function GreaterThan(a As T, b As T) As Boolean
        ...
End Interface
Public Structure Numeric
        Implements INumeric(Of Integer), 
                INumeric(Of Single), ...
        ...
        Public Function GreaterThan(ByVal a As Integer, ByVal b As Integer) As Boolean Implements INumeric(Of Integer).GreaterThan
                Return (a > b)
        End Function
        ...
        Public Function GreaterThan(ByVal a As Single, ByVal b As Single) As Boolean Implements INumeric(Of Single).GreaterThan
                Return (a > b)
        End Function
        ...
End Structure
' Wrapper, to simplify use of Structure Numeric.
Public Structure Num(Of T As {New, IComparable(Of T)}, TNum As {New, INumeric(Of T)})

        Public Shared ReadOnly tn As TNum = New TNum()

        Private ReadOnly value As T

        Public Sub New(a As T)
                Me.value = a
        End Sub


        ' implicitly convert "T" to "Num(Of T, TNum)"; e.g. "11" to "Num(Of Integer, ..) with value 11".
        Public Overloads Shared Widening Operator CType(a As T) As Num(Of T, TNum)
                Return New Num(Of T, TNum)(a)
        End Operator

        ' Implicitly convert "Num(Of T, TNum)" back to "T"; e.g. retrieve value "11".
        Public Overloads Shared Widening Operator CType(a As Num(Of T, TNum)) As T
                Return a.value
        End Operator

        ...
        Public Shared Operator <(a As Num(Of T, TNum), b As Num(Of T, TNum)) As Boolean
                Return tn.LessThan(a.value, b.value)
        End Operator
        ...
End Structure
MyClass的用法:

Public Shared Sub Test()
    Dim v As New MyClass(Of Integer, Numeric)()
    ...
    v.MySub(99)
End Sub
我想消除或简化的一行是:

Dim value As New Num(Of T, TNum)(valueT)
此行仅用于>可以工作的情况。通过将其中一个参数设置为>类型Num,类型T的另一个参数将自动加宽为也为Num,然后找到>

有没有办法改变这些定义,使上面的一行更简单,或者不需要

请注意,我不想要求MySub的参数为Num-这会将负担推到不应该关注此实现细节的代码上-它应该与t一起工作。同样,在>-这里,MaxElement-中使用的另一个值应该是t而不是Num类型。至少在某些情况下;这是一个简化的例子

另一个参考:通用数字的另一个起点是Mark Gravell使用Linq表达式的通用运算符,它是MiscUtil的一部分:

但是Operator.cs中的内部代码对我来说并不熟悉ExpressionUtil.CreateExpression、Expression.Add,我只需要支持少数数字类型,因此不值得理解这种方法并评估其性能。相反,我手工编写了我需要的几个低级方法,用于我需要的几个类型

上述所有方法的所有源材料都是C语言;由于我将其合并到一个VB dll中,所以我决定最终使用一个VB解决方案,而不是引用一个外部dll,以最大限度地提高JIT编译器内联所涉及的简单方法的可能性。也许更了解内部结构的人会得出结论,他们可以以不干扰JIT的方式使用现有的C DLL之一

注意:如果上述方法存在任何性能问题,那么任何性能改进建议都是很好的。此代码用于具有数百万元素的数组图像分析

嵌入大量的VB代码中,这些代码大部分都不是时间关键的,更重要的是程序员的工作效率/更改一些复杂的自定义算法的方便性;到目前为止,不需要孤立代码的一部分,用于重新编写C++,或者使用数字库。好的,后一点是有争议的,但无论如何会有很多自定义VB公式密集型代码,这些代码与其他遗留的VB.Net代码纠缠在一起


最糟糕的情况是,可能必须使用T4生成不同版本的MyClass,每个数值类型一个,而不是使用如图所示的泛型。但如果可能的话,我宁愿避免这种情况——在实际应用程序中,有很多代码,超过了许多类。我们都支持32位的小内存,但现在还需要整数、单和双版本。

简化包装的一种方法:

将方法添加到MyClass或具有相同T/TNum签名的继承基类中,以使转换更加紧凑:

Public Shared Function AsNum(valueT As T) As Num(Of T, TNum)
    Return New Num(Of T, TNum)(valueT)
End Function
然后可以更紧凑地包装参数valueT:

If AsNum(valueT) > Me.MaxElement Then
或者如果将重复使用,并对以下内容进行类型推断:

Dim value = AsNum(valueT)
If value > Me.MaxElement Then
限制:

我有一些继承自T的现有BaseClass的类,我希望避免修改BaseClass以使用Num包装器。所以他们不能通过继承获得AsNum。每个类都需要自己的AsNum方法副本

不能将AsNum放在一个适用于所有类的单独模块中,即公共函数AsNum Of t As{New,IComparableOf t},TNum As{New,INumericOf t}valueT As t As NumOf t,TNum,因为除了在..的类内,无法推断TNum的类型。。特努姆

对于算术运算符+,*在结构Num中,th 关于是以T的身份返回还是以NumOf T,TNum的身份返回,存在一些问题。目前我返回T,因为这似乎更有效,因为我通常将结果存储到T中。但是,这在复杂的表达式中不起作用,因为我一直必须将中间值包装回Num:

vs

使用上面返回Num的第二个表单:对于一些复杂的方法,最干净的解决方案可能是有两个变量, 使用T参数化变量调用Num参数化变量:

Public Shared Function MyFunc(a As T, b As T) As T
    Return MyFunc(AsNum(a), AsNum(b))
End Function
Private Shared Function MyFunc(a As Num(Of T, TNum), b As Num(Of T, TNum)) As Num(Of T, TNum)
    Return a * a + b * b
End Function
T变体用于不知道Num或TNum的外部客户端。 Num变量可以在内部使用,以建立涉及多种方法的计算

这里的要点是,如果最终结果是冗长方法的内部即使对于复杂的公式也很容易读取代码,同时保持良好的性能,并使用几种不同的数值类型,那么我们就需要付出相当多的一次性努力

使用运算符合并现有代码也更容易,只需将声明更改为使用Num和TNum,再加上偶尔需要使用共享的只读tn作为TNum字段来直接访问常用方法

到目前为止,解决方案比我的标准的备选方案要好,但我仍然希望尽可能消除额外的黏性

If AsNum(valueT) > Me.MaxElement Then
Dim value = AsNum(valueT)
If value > Me.MaxElement Then
Structure Num
    ...
    Public Shared Operator +(a As Num(Of T, TNum), b As Num(Of T, TNum)) As T
        Return tn.Add(a.value, b.value)
    End Operator
End Structure
    ...
Class MyClass(Of T As {New, IComparable(Of T)}, TNum As {New, INumeric(Of T)})
    ...
    Public Shared Function MyFunc(a As T, b As T) As T
        Return AsNum(AsNum(a) * a) + AsNum(b) * b
    End Function
End Class
Structure Num(Of T As {New, IComparable(Of T)}, TNum As {New, INumeric(Of T)})
    ...
    ' NOTE: The widening operator automatically converts the "T" from "tn.Add" to a "Num()".
    Public Shared Operator +(a As Num(Of T, TNum), b As Num(Of T, TNum)) As Num(Of T, TNum)
        Return tn.Add(a.value, b.value)
    End Operator
End Structure
    ...
Class MyClass(Of T As {New, IComparable(Of T)}, TNum As {New, INumeric(Of T)})
    ...
    Public Shared Function MyFunc(a As T, b As T) As T
        ' Each sub-expression needs at least one "Num()",
        ' but at least we no longer need a third "AsNum",
        ' for the "+" to work.
        Return AsNum(a) * a + AsNum(b) * b
    End Function
End Class
Public Shared Function MyFunc(a As T, b As T) As T
    Return MyFunc(AsNum(a), AsNum(b))
End Function
Private Shared Function MyFunc(a As Num(Of T, TNum), b As Num(Of T, TNum)) As Num(Of T, TNum)
    Return a * a + b * b
End Function