2 вопроса относительно реализации памятки - PullRequest
2 голосов
/ 07 мая 2011

У меня есть такой класс:

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)

и так далее, но, очевидно, он не очень хорошо масштабируется.

1 Ответ

2 голосов
/ 08 мая 2011

Невозможно написать универсальную функцию на любом языке .NET, которая принимает произвольное количество универсальных параметров, из-за того, как универсальные функции работают в .NET.

Лучше всего либо:

  1. Создайте варианты вашего кода для любого количества параметров, вплоть до чего-то большого (например, 10 или 20?), , как и System.Func<TResult, T1, T2, T3, ...>, .

  2. Используйте Object s в качестве ключей (и Delegate s в качестве функций) вместо универсальных типов.Это снизит безопасность типов и может вызвать резкое замедление, и вы должны использовать его, только если стоимость вызова DynamicInvoke перевешивается скоростью вашей функции .

  3. Используйте другой язык, например C ++, D или Scheme, который поддерживает шаблоны (не очень простой вариант, но я все равно упомянул об этом).

    например, в некоторых языках легко запоминать, например 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
    

И нет, ваш пример не нарушает принцип состояния, потому что ваш статический класс не делаетt состояние удержания!(Вы на самом деле захватываете локальную переменную каждый раз, не повторяя ничего ранее.) Моя же делает.

...