Создает ли лямбда новый экземпляр каждый раз, когда он вызывается? - PullRequest
5 голосов
/ 16 июля 2009

Мне любопытно узнать, будет ли Lambda (при использовании в качестве делегата) создавать новый экземпляр каждый раз, когда он вызывается, или компилятор найдет способ создания экземпляра делегата только один раз и передачи в этом экземпляре.

Точнее говоря, я хочу создать API для игры XNA, который я мог бы использовать лямбда для передачи пользовательского обратного вызова. Поскольку это будет вызываться в методе Update (который вызывается много раз в секунду), было бы очень плохо, если бы он каждый раз обновлял экземпляр для передачи делегата.

InputManager.GamePads.ButtonPressed(Buttons.A, s => s.MoveToScreen<NextScreen>());

Ответы [ 2 ]

3 голосов
/ 26 июля 2009

Меня заинтересовал ваш вопрос, потому что я только что предположил, что такого рода вещи всегда будут генерировать новый объект и, следовательно, его следует избегать в коде, который часто вызывается.

Я делаю что-то похожее, поэтому я решил использовать ildasm, чтобы выяснить, что именно происходит за кулисами. В моем случае оказалось, что каждый раз при вызове делегата создается новый объект, я не буду публиковать свой код, потому что он довольно сложный и не очень простой для понимания вне контекста. Я подозреваю, что это противоречит ответу, предоставленному MichaelGG, поскольку в своем примере он использует статические функции. Я бы посоветовал вам попробовать сами, прежде чем все спроектировать, а потом выяснить, что у вас есть проблема. ildasm - это путь (http://msdn.microsoft.com/en-us/library/f7dy01k1.aspx), ищите любые строки "newobj", они вам не нужны.

Также стоит использовать профиль CLR, чтобы узнать, выделяют ли ваши лямбда-функции память (http://www.microsoft.com/downloads/details.aspx?familyid=A362781C-3870-43BE-8926-862B40AA0CD0&displaylang=en).. Это говорит о том, что это для framework 2.0, но также работает и для 3.5, и это последняя доступная версия.

3 голосов
/ 16 июля 2009

Да, он будет кешировать их, когда сможет:

using System;

class Program {
    static void Main(string[] args) {
        var i1 = test(10);
        var i2 = test(20);
        System.Console.WriteLine(object.ReferenceEquals(i1, i2));
    }

    static Func<int, int> test(int x) {
        Func<int, int> inc = y => y + 1;
        Console.WriteLine(inc(x));
        return inc;
    }
}

Создает статическое поле и, если оно пустое, заполняет его новым делегатом, в противном случае возвращает существующий делегат.

Выходы 10, 20, правда.

...