Встроенные функции в C #?
Как вы выполняете «встроенные функции» на C #? Я не думаю, что понимаю концепцию. Они похожи на анонимные методы? Как lambda-функции?
Примечание . Ответы почти полностью касаются возможности встроенных функций , то есть «руководство или оптимизация компилятора, которая заменяет сайт вызова функции телом вызываемого абонента». Если вас интересуют анонимные функции (aka lambda) , см . Ответ @ jalf или Что это за «lambda», о котором все говорят? ,
- Измерение фактического времени выполнения MySQL
- Кеширование целых чисел в Java
- Что такое оптимизация кода и возврат значения?
- Что более эффективно? Используя pow для квадрата или просто умножьте его на себя?
- Почему транспонирование матрицы 512x512 намного медленнее, чем перенос матрицы 513x513?
- Самый эффективный способ конкатенации строк?
- Почему лямбды лучше оптимизируются компилятором, чем простые функции?
- Каков самый быстрый способ конвертировать float в int на x86
- Могут ли компиляторы исключать бесконечные петли?
- Каков самый быстрый / самый эффективный способ найти самый старший бит набора (msb) в целых числах в C?
- Оптимизация Hyperparameter для глубоких обучающих структур с использованием байесовской оптимизации
- Каков выигрыш от объявления метода как статического
- Взаимоотношения Groovy в отношении пространства / времени
Наконец, в .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.
Особенно учитывая Mono (который открыт), существуют некоторые monoспецифические технические ограничения, учитывающие встроенный или более общий (например, виртуальные функции). В целом, да, это подсказка для компилятора, но я думаю, это то, о чем просили.
Встроенные методы – это просто оптимизация компилятора, где код функции передается в вызывающий.
В C # нет механизма для этого, и они должны использоваться экономно на языках, где они поддерживаются – если вы не знаете, почему их следует где-то использовать, их не должно быть.
Изменить: Чтобы уточнить, есть две основные причины, по которым их нужно использовать экономно:
- Легко создавать массивные двоичные файлы, используя встроенные в случаях, когда это не обязательно
- Компилятор имеет тенденцию знать лучше, чем вы, когда что-то должно, с точки зрения производительности, быть встроенным
Лучше оставить все в покое и позволить компилятору выполнять свою работу, затем профиль и выяснить, подходит ли встроенное приложение для вас. Конечно, некоторые вещи имеют смысл быть встроенными (в частности, математические операторы), но позволяя компилятору справиться с ним, как правило, это лучшая практика.
Обновление: на ответ от konrad.kruczynski верно следующее для версий .NET до 4.0 включительно.
Вы можете использовать class MethodImplAttribute, чтобы предотвратить включение метода …
[MethodImpl(MethodImplOptions.NoInlining)] void SomeMethod() { // ... }
… но нет никакого способа сделать противоположное и заставить его быть встроенным.
Вы смешиваете две отдельные концепции. Функция inlining – это оптимизация компилятора, которая не влияет на семантику. Функция ведет себя одинаково независимо от того, является ли она встроенной или нет.
С другой стороны, lambda-функции являются чисто семантическим понятием. Нет требования о том, как они должны выполняться или выполняться, если они следуют за поведением, изложенным в спецификации языка. Они могут быть встроены, если компилятор JIT чувствует себя так, или нет, если это не так.
В C # нет ключевого слова inline, потому что это оптимизация, которую обычно можно оставить компилятору, особенно на языках JIT. JIT-компилятор имеет доступ к статистике времени выполнения, которая позволяет ему решать, что делать встроенным гораздо эффективнее, чем вы можете при написании кода. Функция будет включена, если компилятор решит, и вы ничего не можете с этим поделать. 🙂
Вы имеете в виду встроенные функции в смысле C ++? В чем содержимое нормальной функции автоматически копируется в очередь в callsite? Конечным эффектом является то, что при вызове функции вызов функции фактически не происходит.
Пример:
inline int Add(int left, int right) { return left + right; }
Если это так, то нет, для этого нет эквивалента C #.
Или вы имеете в виду функции, объявленные в рамках другой функции? Если да, то да, C # поддерживает это с помощью анонимных методов или lambda-выражений.
Пример:
static void Example() { Func 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 BuildListAndOutput(IEnumerable x) { // let's pretend IEnumerable.ToList() doesn't exist for the moment IList result = new List (); foreach(string y in x) { result.Add(y); OutputItem(y); } return result; }
Оптимизатор Just-In-Time компилятора может изменить код, чтобы избежать повторного размещения вызова OutputItem () в стеке, так что было бы так, как если бы вы написали такой код:
public IList BuildListAndOutput(IEnumerable x) { IList result = new List (); foreach(string y in x) { result.Add(y); // full OutputItem() implementation is placed here Console.WriteLine(y); } return result; }
В этом случае мы бы сказали, что функция OutputItem () была встроена. Обратите внимание, что это может сделать это, даже если OutputItem () вызывается из других мест.
Отредактировано, чтобы показать сценарий, который скорее всего будет встроен.
Да. Именно, единственным отличием является то, что он возвращает значение.
Упрощение (без использования выражений):
List
Принимает действие, оно не ожидает результата возврата.
Поэтому делегату Action
хватило бы .. скажите:
List.ForEach(param => Console.WriteLine(param));
это то же самое, что сказать:
List.ForEach(delegate(T param) { Console.WriteLine(param); });
разница заключается в том, что тип параметра и делегирование делегатов выводятся по использованию, а фигурные скобки не требуются для простого встроенного метода.
В то время как
List
функцию, ожидая результата.
Таким образом, ожидается Function
:
List.Where(param => param.Value == SomeExpectedComparison);
это то же самое, что:
List.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
Вы также можете объявить эти методы inline и присвоить их переменным IE:
Action myAction = () => Console.WriteLine("I'm doing something Nifty!"); myAction();
или
Function
Надеюсь, это поможет.
Бывают случаи, когда я хочу заставить код быть выровненным.
Например, если у меня есть сложная процедура, в которой существует большое количество решений, принимаемых в очень итеративном блоке, и эти решения приводят к аналогичным, но немного отличающимся действиям. Рассмотрим, например, сложный (не основанный на БД) сортировщик сортировки, где алгоритм сортировки сортирует элементы в соответствии с рядом различных несвязанных критериев, например, если они сортируют слова в соответствии с грамматическими, а также семантическими критериями для быстрого языка система распознавания. Я хотел бы написать вспомогательные функции для обработки этих действий, чтобы поддерживать читаемость и модульность исходного кода.
Я знаю, что эти вспомогательные функции должны быть очерчены, потому что именно так будет написан код, если он никогда не должен был быть понят человеком. Я бы, конечно же, хотел бы обеспечить в этом случае, что не было функции вызова вызова.
Утверждение «лучше всего оставить эти вещи в покое и позволить компилятору выполнить эту работу». (Cody Brocious) – полный рубит. Я программировал высокопроизводительный игровой код в течение 20 лет, и мне еще предстоит встретить компилятор, который достаточно «умный», чтобы знать, какой код должен быть встроен (функции) или нет. Было бы полезно иметь оператор «inline» в c #, правда в том, что компилятор просто не имеет всей информации, необходимой ему для определения того, какая функция должна быть всегда встроена или нет без подсказки «inline». Конечно, если функция маленькая (accessor), то она может быть автоматически встроена, но что, если это несколько строк кода? Nonesense, компилятор не может знать, вы не можете просто оставить это до компилятора для оптимизированного кода (вне алгоритмов).
Нет, такой конструкции нет в C #, но компилятор .NET JIT может решить делать встроенные вызовы функций во время JIT. Но я действительно не знаю, действительно ли это делает такие оптимизации.
(Я думаю, это должно :-))
Если ваши сборки будут опубликованы, вы можете взглянуть на TargetedPatchingOptOut. Это поможет ngen решить, использовать ли встроенные методы. Ссылка на MSDN
Это все еще только декларативный намек на оптимизацию, а не обязательную команду.
Я знаю, что этот вопрос касается C #. Тем не менее, вы можете писать встроенные функции в .NET с помощью F #. см.: Использование `inline` в F #
C # не поддерживает встроенные методы (или функции) в том, как это делают динамические языки, такие как python. Однако анонимные методы и lambdas могут использоваться для аналогичных целей, в том числе, когда вам нужно получить доступ к переменной в методе, как в приведенном ниже примере.
static void Main(string[] args) { int a = 1; Action inline = () => a++; inline(); //here a = 2 }
Лямбда-выражения являются встроенными функциями! Я думаю, что у C # нет дополнительного атрибута, например встроенного или что-то в этом роде!