gpt4 book ai didi

.net - 柯里化(Currying)委托(delegate)参数的最佳模式是什么(使用 .NET 2.0 或更高版本)?

转载 作者:行者123 更新时间:2023-12-03 03:17:48 25 4
gpt4 key购买 nike

有时,进行方法调用(包含参数)并将其转换为 MethodInvoker 会很有用,该 MethodInvoker 将使用这些参数调用指示的函数,而无需当时指定参数。在其他时候,做类似的事情很有用,但保留一些参数。这种类型的 Action 称为“Currying”。在 VB 中执行此操作的最佳模式是什么?

可以在 VB 2010 中使用 lambda 表达式,但 lambda 表达式与编辑并继续不兼容,并且它们创建的闭包可能会出现意外的引用行为。另一种方法是定义一些通用方法,如下所示:

Public Module CurryMagic
Delegate Sub Action(Of T1, T2)(ByVal P1 As T1, ByVal P2 As T2)
Delegate Sub Action(Of T1, T2, T3)(ByVal P1 As T1, ByVal P2 As T2, ByVal P3 As T3)

Class CurriedAction0(Of FixedType1, FixedType2)
Dim _theAction As Action(Of FixedType1, FixedType2)
Dim _FixedVal1 As FixedType1, _FixedVal2 As FixedType2
Sub Exec()
_theAction(_FixedVal1, _FixedVal2)
End Sub
Sub New(ByVal theAction As Action(Of FixedType1, FixedType2), _
ByVal FixedVal1 As FixedType1, ByVal FixedVal2 As FixedType2)
_theAction = theAction
_FixedVal1 = FixedVal1
_FixedVal2 = FixedVal2
End Sub
End Class

Class CurriedAction1(Of ArgType1, FixedType1, FixedType2)
Dim _theAction As Action(Of ArgType1, FixedType1, FixedType2)
Dim _FixedVal1 As FixedType1, _FixedVal2 As FixedType2
Sub Exec(ByVal ArgVal1 As ArgType1)
_theAction(ArgVal1, _FixedVal1, _FixedVal2)
End Sub
Sub New(ByVal theAction As Action(Of ArgType1, FixedType1, FixedType2), _
ByVal FixedVal1 As FixedType1, ByVal FixedVal2 As FixedType2)
_theAction = theAction
_FixedVal1 = FixedVal1
_FixedVal2 = FixedVal2
End Sub
End Class

Class ActionOf(Of ArgType1)
Shared Function Create(Of FixedType1, FixedType2)(ByVal theSub As Action(Of ArgType1, FixedType1, FixedType2), ByVal FixedVal1 As FixedType1, ByVal FixedVal2 As FixedType2) As Action(Of ArgType1)
Return AddressOf New CurriedAction1(Of ArgType1, FixedType1, FixedType2)(theSub, FixedVal1, FixedVal2).Exec
End Function
End Class

Function NewInvoker(Of FixedType1, FixedType2)(ByVal theSub As Action(Of FixedType1, FixedType2), ByVal FixedVal1 As FixedType1, ByVal FixedVal2 As FixedType2) As MethodInvoker
Return AddressOf New CurriedAction0(Of FixedType1, FixedType2)(theSub, FixedVal1, FixedVal2).Exec
End Function
End Module

如果我想创建一个执行 Foo(5, "Hello") 的 MethodInvoker,我可以使用创建一个

MyInvoker = NewInvoker(AddressOf Foo, 5, "Hello")

如果我想将 MyAction(X) 转换为 Boz(X, "George", 9),其中 X 是 Double,我可以使用

MyAction = ActionOf(Of Double).Create(AddressOf Boz, "George", 9)

一切都非常巧妙,只是需要有大量的样板代码来容纳不同数量的固定和非固定参数,并且委托(delegate)创建语法中没有任何固有的内容可以明确哪些参数是固定的,哪些参数是固定的。是非固定的。有没有办法改进模式?

附录:如果从结构体成员函数创建委托(delegate),其机制是什么?看起来委托(delegate)获得了自己的结构副本,但我不知道该副本是否已装箱或未装箱。如果未装箱,则用结构替换 CurryAction0 和 CurryAction1 将避免在创建委托(delegate)时将 CurryAction0 或 CurryAction1 分配为单独的堆对象。但是,如果要对其进行装箱,则使用结构会增加将结构复制到装箱实例的开销,同时不会保存任何内容。

最佳答案

如果你可以使用.Net 4,tuples怎么样? ?

    ''Create new tuple instance with two items.
Dim tuple As Tuple(Of Integer, String) = _
New Tuple(Of Integer, String)(5, "Hello")
''Now you only have one argument to curry, packaging both parameters
''Access the parameters like this (strongly typed)
Debug.Print tuple.Item1 '' 5
Debug.Print tuple.Item2 '' "Hello"

关于.net - 柯里化(Currying)委托(delegate)参数的最佳模式是什么(使用 .NET 2.0 或更高版本)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4516155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com