我有一个这样的课程:
Public NotInheritable Class F
Private Sub New()
End Sub
Public Shared Function Mize(Of TResult)(ByVal f As System.Func(Of TResult)) As System.Func(Of TResult)
Dim is_new = True
Dim result As TResult
Return Function()
If is_new Then
result = f()
End If
Return result
End Function
End Function
Public Shared Function Mize(Of T, TResult)(ByVal f As System.Func(Of T, TResult)) As System.Func(Of T, TResult)
Dim is_new_s = New System.Collections.Generic.List(Of Boolean)
Dim inputs = New System.Collections.Generic.List(Of T)
Dim d = New System.Collections.Generic.Dictionary(Of T, TResult)
Return Function(arg1 As T)
If d.ContainsKey(arg1) Then
Return d.Item(arg1)
Else
Dim result = f(arg1)
d.Add(arg1, result)
Return result
End If
End Function
End Function End Class
我想知道
1)这是否违反短语静态类不应该有状态?
2)我如何修改功能,使他们可以接受任何功能(而不是我的上述情况,只适用于F(TResult)
和F(T, TResult)
。我的意思是我可以创建另一个功能:
Function Mize(Of T, T2, TResult)(ByVal f As System.Func(Of T, T2, TResult))
As System.Func(Of T, T2, TResult)
等等,但显然它根本不能很好地扩展。
答案 0 :(得分:2)
由于泛型在.NET中的工作方式,因此无法在任何带有任意数量通用参数的.NET语言中编写泛型函数。
你最好的选择是:
为任意数量的参数设置代码的变体(例如10或20?),就像System.Func<TResult, T1, T2, T3, ...>
那样。
使用Object
作为键(和Delegate
s作为函数),而不是泛型类型。这会降低类型安全性并导致显着的减速,并且如果功能速度超过调用DynamicInvoke
的成本,则仅使用它。
使用其他语言,如C ++,D或Scheme,它们支持模板(不是一个非常简单的选项,但无论如何我都提到过)。
e.g。在某些语言中,记忆很容易,例如D:
auto memoize(alias F, T...)(T args)
{
auto key = tuple(args); //Pack args into one
static typeof(F(args))[typeof(key)] cache; //Dictionary
return key in cache ? cache[key] : (cache[key] = F(args));
}
可以很容易地使用,如:
result = memoize!(func)(args); //Calls a memoized 'func' with args
不,你的例子没有违反州原则,因为你的静态类没有保持状态! (你实际上每次都在捕获一个局部变量,而不是重复使用之前的任何东西。)但我的确如此。