Подтвердить что ты не робот

Как сделать встроенные функции в С#

Я использую Linq To XML

new XElement("Prefix", Prefix == null ? "" : Prefix)

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

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

4b9b3361

Ответ 1

Да, С# поддерживает это. Доступно несколько синтаксисов:

  • Анонимные методы (доступны с С# 2 и далее)

    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!");
                             }
    
  • Выражение Lambdas (доступно с С# 3 и далее)

    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
    
  • Заявление lambdas (доступно с С# 3 и далее)

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

Для них существуют два разных типа: Func и Action. Func возвращать значения, но 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 onwards

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

int x = add(23,17); // x == 40
print(x); // outputs 40
helloWorld(x); // helloWord has one int parameter declared: Action<int>
               // even though it does not make any use of it.

Ответ 3

Ответ на ваш вопрос - да и нет, в зависимости от того, что вы подразумеваете под "встроенной функцией". Если вы используете термин, как он используется в разработке на С++, тогда ответ будет отрицательным, вы не можете этого сделать - даже выражение лямбда - это вызов функции. Хотя верно, что вы можете определять встроенные лямбда-выражения для замены деклараций функций в С#, компилятор все равно заканчивает создание анонимной функции.

Вот какой действительно простой код, который я использовал для тестирования этого (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/С++, для выполнения этой работы.

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

"Преждевременная оптимизация - это корень всех злых (или, по крайней мере, большей части) в программировании". - Дональд Кнут

"Программа, которая работает неправильно, не требует быстрого запуска" - Me

Ответ 4

Вы можете использовать Func, который инкапсулирует метод с одним параметром и возвращает значение типа, заданного параметром TResult.

void Method()
{
    Func<string,string> inlineFunction = source => 
    {
        // add your functionality here
        return source ;
     };


    // call the inline function
   inlineFunction("prefix");
}