Избегайте повторного выделения объекта Action без переменной / члена - PullRequest
0 голосов
/ 02 февраля 2012

Часто мне нужно минимизировать распределение объектов в коде, который выполняется очень часто.
Конечно, я могу использовать обычные методы, такие как пул объектов, но иногда мне просто нужно что-то локально.
Чтобы попытаться достичь этого, я придумал следующее:

public static class Reusable<T> where T : new()
{
    private static T _Internal;
    private static Action<T> _ResetAction;

    static Reusable()
    {
        _Internal = Activator.CreateInstance<T>();
    }

    public static void SetResetAction(Action<T> resetAction)
    {
        _ResetAction = resetAction;
    }

    public static T Get()
    {
#if DEBUG
        if (_ResetAction == null)
        {
            throw new InvalidOperationException("You must set the reset action first");
        }
#endif

        _ResetAction(_Internal);

        return _Internal;
    }
}

В настоящее время использование будет:

// In initialisation function somewhere
Reuseable<List<int>>.SetResetAction((l) => l.Clear());

....

// In loop
var list = Reuseable<List<int>>.Get();
// Do stuff with list

Что я хотел бы улучшить, так это тот факт, что все это не содержится в одном месте (.SetResetAction отделено от того, где оно фактически используется).

Я бы хотел получить код примерно так:

// In loop

var list = Reuseable<List<int>>.Get((l) => l.Clear());
// Do stuff with list

Проблема в том, что я получаю распределение объектов (оно создает Action<T>) каждый цикл.

Можно ли получить нужное мне использование без каких-либо выделений объектов?

Очевидно, я мог бы создать ReuseableList<T> со встроенным Action, но я хочу учесть другие случаи, когда действие может отличаться.

1 Ответ

4 голосов
/ 02 февраля 2012

Вы уверены , что создает новый Action<T> на каждой итерации?Я подозреваю, что на самом деле это не так, учитывая, что он не фиксирует никаких переменных.Я подозреваю, что если вы посмотрите на IL, сгенерированный компилятором C #, он кеширует делегат.

Конечно, это зависит от реализации ...

РЕДАКТИРОВАТЬ: (Я просто ушел раньшеУ меня было время написать больше ...)

Как указывает Эрик в комментарии, полагаться на это не очень хорошая идея.Это не гарантировано, и легко случайно его сломать, даже если вы не меняете компилятор.

Даже дизайн этого выглядит тревожно (безопасность потоков?), Но если вы должны сделать этоЯ бы, вероятно, превратил его из статического класса в «нормальный» класс, который принимает метод сброса (и, возможно, экземпляр) в конструкторе.Это более гибкий, читаемый и тестируемый подход IMO.

...