Встроенные функции в С#?

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

Примечание. Ответы почти полностью касаются возможности встроенных функций, то есть "оптимизация вручную или компилятора который заменяет узел вызова функции телом вызываемого абонента". Если вас интересуют функции анонимные (aka lambda), см. @jalf answer или О чем говорит этот "Лямбда" ?.

Ответ 1

Наконец, в .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. Раньше здесь использовалась "сила". Поскольку было несколько downvotes, я попытаюсь прояснить этот термин. Как и в комментариях и документации, The method should be inlined if possible. Особенно учитывая Моно (что открыто), существуют некоторые моноспецифические технические ограничения, рассматривающие вложение или более общую (например, виртуальные функции). В целом, да, это подсказка для компилятора, но я думаю, это то, о чем просили.

Ответ 2

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

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

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

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

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

Ответ 3

Обновление: В konrad.kruczynski answer, это верно для версий .NET до 4.0 и включает 4.0.

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

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

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

Ответ 4

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

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

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

Ответ 5

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

Пример:

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

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

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

Пример:

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

Ответ 6

Cody имеет это право, но я хочу привести пример того, что такое встроенная функция.

Скажем, у вас есть этот код:

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 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() из других мест.

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

Ответ 7

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

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

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; });

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

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

myAction();

или

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

string myString = myFunction(someObject);

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

Ответ 8

Есть случаи, когда я хочу заставить код быть вложенным.

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

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

Ответ 9

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

Ответ 10

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

Ответ 11

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

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

Ответ 12

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

Ответ 13

У меня есть метод, который возвращает true/false при запуске в режиме отладки. У меня есть несколько проверок безопасности, которые обойдутся в режиме отладки.

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

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

Может быть, когда мы перейдем к 4.5, я думаю...

Ответ 14

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

static void Main(string[] args)
{
    int a = 1;

    Action inline = () => a++;
    inline();
    //here a = 2
}

Ответ 15

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