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



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



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

1085   14  

14 ответов:

наконец, в .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. особенно учитывая моно (который открыт), есть некоторые моно-специфические технические ограничения рассматривая встраивание или более общий (например, виртуальные функции). В целом, да, это подсказка для компилятора, но я думаю, что это то, что было предложено.

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

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

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

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

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

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

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

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

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

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

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

в C# нет встроенного ключевого слова, потому что это оптимизация, которую обычно можно оставить компилятору, особенно в jit'Ed языках. 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;
}

The компиляторJust-In-Time optimizer может изменить код, чтобы избежать повторного вызова 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; });

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

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

myAction();

или

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

string myString = myFunction(someObject);

Я надеюсь, что это помогает.

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

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

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

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

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

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

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

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

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

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

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

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

Comments

    Ничего не найдено.