Вопрос

Как вы выполняете «встроенные функции» в C#?Я не думаю, что понимаю эту концепцию.Они похожи на анонимные методы?Нравятся лямбда-функции?

Примечание:Ответы почти полностью касаются способности встроенные функции, т.е.«Оптимизация ручной или компиляторы, которая заменяет сайт вызова функции на корпус Callee». Если вы заинтересованы в анонимный (т.лямбда) функции, видеть Ответ @jalf или Что это за «Лямбда», о которой все постоянно говорят?.

Это было полезно?

Решение

Наконец, в .NET 4.5 CLR позволяет подсказывать/подсказывать.1 встраивание метода с использованием MethodImplOptions.AggressiveInlining ценить.Он также доступен в багажнике Mono (запущен сегодня).

// The full attribute usage is in mscorlib.dll,
// so should not need to include extra references
using System.Runtime.CompilerServices; 

...

[MethodImpl(MethodImplOptions.AggressiveInlining)]
void MyMethod(...)

1.Раньше здесь применялась «сила».Поскольку было несколько отрицательных голосов, я попытаюсь уточнить этот термин.Как в комментариях и документации, The method should be inlined if possible. Особенно учитывая Mono (который является открытым), существуют некоторые технические ограничения, специфичные для моно, с учетом встраивания или более общего (например, виртуальных функций).В целом да, это подсказка компилятору, но, думаю, именно об этом и просили.

Другие советы

Встроенные методы - это просто оптимизация компилятора, когда код функции свернут в вызывающую функцию.

Нет механизма, с помощью которого это можно сделать в C #, и они будут использоваться экономно в тех языках, где они поддерживаются - если вы не знаете, почему их нужно где-то использовать, их не должно быть.

Изменить. Чтобы уточнить, есть две основные причины, по которым их следует использовать с осторожностью:

<Ол>
  • Легко создавать массивные двоичные файлы, используя inline, если в этом нет необходимости
  • Компилятор имеет тенденцию знать лучше, чем вы, когда что-то должно быть с точки зрения производительности встроено
  • Лучше оставить все как есть и позволить компилятору выполнить свою работу, а затем профилировать и выяснить, является ли inline лучшим решением для вас. Конечно, некоторые вещи имеют смысл встраивать (в частности, в математические операторы), но, как правило, использование компилятора - это лучший метод.

    Обновление: Согласно ответу konrad.kruczynski , верно следующее для версий. NET до 4.0 включительно.

    Вы можете использовать класс MethodImplAttribute чтобы предотвратить метод от встроенного ...

    [MethodImpl(MethodImplOptions.NoInlining)]
    void SomeMethod()
    {
        // ...
    }
    

    ... но нет способа сделать обратное и принудительно сделать это встроенным.

    Вы смешиваете две разные концепции. Встраивание функций - это оптимизация компилятора, которая не влияет на семантику. Функция ведет себя одинаково независимо от того, встроена она или нет.

    С другой стороны, лямбда-функции - это чисто семантическая концепция. Нет требований к тому, как они должны быть реализованы или выполнены, если они следуют поведению, изложенному в спецификации языка. Они могут быть встроены, если JIT-компилятор чувствует себя так, или нет, если это не так.

    В C # нет встроенного ключевого слова, потому что это оптимизация, которую обычно можно оставить компилятору, особенно в языках JIT. JIT-компилятор имеет доступ к статистике времени выполнения, что позволяет ему решать, что встроить гораздо эффективнее, чем вы можете при написании кода. Функция будет встроена, если компилятор решит, и вы ничего не можете с этим поделать. :)

    Вы имеете в виду встроенные функции в смысле C++?В котором содержимое обычной функции автоматически копируется в сайт вызова?Конечным результатом является то, что при вызове функции на самом деле не происходит никакого вызова функции.

    Пример:

    inline int Add(int left, int right) { return left + right; }
    

    Если да, то нет, эквивалента этому на C# не существует.

    Или вы имеете в виду функции, объявленные внутри другой функции?Если да, то да, C# поддерживает это с помощью анонимных методов или лямбда-выражений.

    Пример:

    static void Example() {
      Func<int,int,int> add = (x,y) => x + y;
      var result = add(4,6);  // 10
    }
    

    Коди все правильно, но я хочу привести пример того, что такое встроенная функция.

    Допустим, у вас есть этот код:

    private void OutputItem(string x)
    {
        Console.WriteLine(x);
    
        //maybe encapsulate additional logic to decide 
        // whether to also write the message to Trace or a log file
    }
    
    public IList<string> BuildListAndOutput(IEnumerable<string> x)
    {  // let's pretend IEnumerable<T>.ToList() doesn't exist for the moment
        IList<string> result = new List<string>();
    
        foreach(string y in x)
        {
            result.Add(y);
            OutputItem(y);
        }
        return result;
    }
    

    Оптимизатор Just-In-Time компилятора может изменить код, чтобы избежать повторного вызова функции OutputItem () в стеке, так что это было бы так, как если бы вы написали код как это вместо этого:

    public IList<string> BuildListAndOutput(IEnumerable<string> x)
    {
        IList<string> result = new List<string>();
    
        foreach(string y in x)
        {
            result.Add(y);
    
            // full OutputItem() implementation is placed here
            Console.WriteLine(y);   
        }
    
        return result;
    }
    

    В этом случае мы бы сказали, что функция OutputItem () была встроенной. Обратите внимание, что это может быть сделано, даже если OutputItem () вызывается и из других мест.

    Отредактировано, чтобы показывать сценарий с большей вероятностью быть встроенным.

    Да, именно так, единственное отличие заключается в том, что он возвращает значение.

    Упрощение (без использования выражений):

    List<T>.ForEach Выполняет действие, не ожидает возвращаемого результата.

    Итак, Action<T> делегата будет достаточно..сказать:

    List<T>.ForEach(param => Console.WriteLine(param));
    

    это то же самое, что сказать:

    List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });
    

    разница в том, что тип параметра и объявление делегата определяются в зависимости от использования, а фигурные скобки не требуются для простого встроенного метода.

    Тогда как

    List<T>.Where Принимает функцию, ожидая результата.

    Итак, Function<T, bool> следовало бы ожидать:

    List<T>.Where(param => param.Value == SomeExpectedComparison);
    

    что то же самое, что:

    List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
    

    Вы также можете объявить эти методы встроенными и назначить их переменным IE:

    Action myAction = () => Console.WriteLine("I'm doing something Nifty!");
    
    myAction();
    

    или

    Function<object, string> myFunction = theObject => theObject.ToString();
    
    string myString = myFunction(someObject);
    

    Надеюсь, это поможет.

    В некоторых случаях я хочу, чтобы код был встроен.

    Например, если у меня есть сложная процедура, в которой большое количество решений принимается в рамках итеративного блока, и эти решения приводят к аналогичным, но немного отличающимся действиям, которые необходимо выполнить. Рассмотрим, например, комплексный (не управляемый БД) сортировщик сравнения, в котором алгоритм сортировки сортирует элементы по ряду различных несвязанных критериев, как, например, можно было бы сделать, если бы они сортировали слова по грамматическим и семантическим критериям для быстрого языка. система распознавания. Я хотел бы написать вспомогательные функции для обработки этих действий, чтобы обеспечить удобочитаемость и модульность исходного кода.

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

    Утверждение & "Лучше всего оставить все это в покое и позволить компилятору выполнить работу .. " (Коди Брошиус) - это полная чушь. Я программировал высокопроизводительный игровой код в течение 20 лет, и мне еще не приходилось сталкиваться с «достаточно умным» компилятором, чтобы знать, какой код должен быть встроен (функции) или нет. Было бы полезно иметь & Quot; inline & Quot; утверждение в C #, правда в том, что компилятор просто не имеет всей информации, необходимой для определения, какая функция должна быть всегда встроенной или нет без " inline " намек. Конечно, если функция маленькая (accessor), то она может быть автоматически вставлена, но что, если это несколько строк кода? Безусловно, компилятор не знает, вы не можете просто оставить это на усмотрение компилятора (кроме алгоритмов).

    Нет, в C # такой конструкции нет, но JIT-компилятор .NET может решить выполнять вызовы встроенных функций во время JIT. Но я на самом деле не знаю, действительно ли он делает такие оптимизации.
    (я думаю, что должен: -))

    Если ваши сборки будут созданы, вы можете взглянуть на TargetedPatchingOptOut. Это поможет ngen решить, следует ли использовать встроенные методы. ссылка на MSDN

    Это все еще только декларативная подсказка для оптимизации, но не обязательная команда.

    Я знаю, что этот вопрос касается C #. Тем не менее, вы можете написать встроенные функции в .NET с помощью F #. см .: Использование `inline` в F #

    Лямбда-выражения являются встроенными функциями! Я думаю, что у C # нет лишнего атрибута, такого как inline или что-то в этом роде!

    C # не поддерживает встроенные методы (или функции), как это делают динамические языки, такие как python. Однако анонимные методы и лямбды могут использоваться для аналогичных целей, в том числе, когда вам нужно получить доступ к переменной в содержащем метод, как в примере ниже.

    static void Main(string[] args)
    {
        int a = 1;
    
        Action inline = () => a++;
        inline();
        //here a = 2
    }
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top