Как делают встроенные функции в C#
Я использую Linq to XML
new XElement("Prefix", Prefix == null ? "" : Prefix)
но я хочу сделать некоторые вычисления для префикса, прежде чем добавлять его в xml, например, устраняя пробелы, специальные символы, некоторые вычисления и т. д.
Я не хочу создавать функции, потому что это не поможет в любой другой части моей программы, но это, так есть ли способ создать встроенные функции??
6 ответов:
да, C# поддерживает это. Есть несколько доступных синтаксисов.
анонимные методы были добавлены в C# 2.0:
Func<int, int, int> add = delegate(int x, int y) { return x + y; }; Action<int> print = delegate(int x) { Console.WriteLine(x); } Action<int> helloWorld = delegate // parameters can be elided if ignored { Console.WriteLine("Hello world!"); }
лямбда новичок в C# 3.0 и выпускаются в двух вариантах.
выражения-лямбды:
Func<int, int, int> add = (int x, int y) => x + y; // or... Func<int, int, int> add = (x, y) => x + y; // types are inferred by the compiler
лямбды:
Action<int> print = (int x) => { Console.WriteLine(x); }; Action<int> print = x => { Console.WriteLine(x); }; // inferred types Func<int, int, int> add = (x, y) => { return x + y; };
местные функции были введены с C# 7.0:
int add(int x, int y) => x + y; void print(int x) { Console.WriteLine(x); }
есть в основном два различных типа этих:
Func
иAction
.Func
s возвращаемые значения, ноAction
не. Последний параметр типаFunc
- это тип возвращаемого значения; все остальные типы параметров.есть похожие типы с разными именами, но синтаксис для объявления их inline одинаковый. Примером этого является
Comparison<T>
, что примерно эквивалентноFunc<T, T, int>
.Func<string, string, int> compare1 = (l,r) => 1; Comparison<string> compare2 = (l, r) => 1; Comparison<string> compare3 = compare1; // this one only works from C# 4.0 onwards
они могут использоваться непосредственно, как если бы они были обычными методами:
int x = add(23, 17); // x == 40 print(x); // outputs 40 helloWorld(x); // helloWorld has one int parameter declared: Action<int> // even though it does not make any use of it.
да.
вы можете создать анонимные методы или лямбда-выражения:
Func<string, string> PrefixTrimmer = delegate(string x) { return x ?? ""; }; Func<string, string> PrefixTrimmer = x => x ?? "";
ответ на ваш вопрос-да и нет, в зависимости от того, что вы подразумеваете под "встроенной функцией". Если вы используете этот термин, как он используется в разработке на C++, то ответ Нет, вы не можете этого сделать - даже лямбда-выражение-это вызов функции. Хотя верно, что вы можете определить встроенные лямбда-выражения для замены объявлений функций в C#, компилятор все равно создает анонимную функцию.
вот некоторые очень простой код, который я использовал, чтобы проверить это (VS2015):
static void Main(string[] args) { Func<int, int> incr = a => a + 1; Console.WriteLine($"P1 = {incr(5)}"); }
что генерирует компилятор? Я использовал отличный инструмент под названием ILSpy, который показывает фактическую сборку IL. Посмотрите (я опустил много материала настройки класса)
Это основная функция:
IL_001f: stloc.0 IL_0020: ldstr "P1 = {0}" IL_0025: ldloc.0 IL_0026: ldc.i4.5 IL_0027: callvirt instance !1 class [mscorlib]System.Func`2<int32, int32>::Invoke(!0) IL_002c: box [mscorlib]System.Int32 IL_0031: call string [mscorlib]System.String::Format(string, object) IL_0036: call void [mscorlib]System.Console::WriteLine(string) IL_003b: ret
видите эти строки IL_0026 и IL_0027? Эти две инструкции загружают число 5 и вызывают функцию. Затем il_0031 и IL_0036 форматируют и печатают результат.
и вот функция звонил:
.method assembly hidebysig instance int32 '<Main>b__0_0' ( int32 a ) cil managed { // Method begins at RVA 0x20ac // Code size 4 (0x4) .maxstack 8 IL_0000: ldarg.1 IL_0001: ldc.i4.1 IL_0002: add IL_0003: ret } // end of method '<>c'::'<Main>b__0_0'
Это очень короткая функция, но это функция.
стоит ли это каких-либо усилий по оптимизации? Нет. Возможно, если вы вызываете его тысячи раз в секунду, но если производительность так важна, то вы должны рассмотреть возможность вызова собственного кода, написанного на C/C++, чтобы выполнить эту работу.
по моему опыту читаемость и ремонтопригодность почти всегда важнее, чем оптимизация за несколько микросекунд прироста скорости. Используйте функции, чтобы сделать ваш код читается и контролировать переменную область видимости и не беспокоиться о производительности.
"преждевременная оптимизация является корнем всего зла (или, по крайней мере, большей его части) в программировании." -- Дональд Кнут
" программа, которая не работает правильно, не должна работать быстро" -- Я
C# 7 добавляет поддержку локальные функции
вот предыдущий пример использования локальной функции
void Method() { string localFunction(string source) { // add your functionality here return source ; }; // call the inline function localFunction("prefix"); }
можно использовать Func, который инкапсулирует метод, который принимает один параметр и возвращает значение типа, указанного в параметре TResult.
void Method() { Func<string,string> inlineFunction = source => { // add your functionality here return source ; }; // call the inline function inlineFunction("prefix"); }