如何在C#中创建内联函数

Joe*_*xon 75 .net c#

我正在使用Linq To XML

new XElement("Prefix", Prefix == null ? "" : Prefix)
Run Code Online (Sandbox Code Playgroud)

但是我想在将它添加到xml之前对前缀进行一些计算,比如消除空格,特殊字符,一些计算等

我不想创建函数,因为这些函数对我的程序的任何其他部分都没有任何帮助,但是这样,有没有办法创建内联函数?

R. *_*des 188

是的,C#支持这一点.有几种语法可用.

这些基本上有两种不同的类型:FuncAction.Funcs返回值,但Action不是.a的最后一个类型参数Func是返回类型; 所有其他都是参数类型.

有类似的类型具有不同的名称,但声明它们内联的语法是相同的.这方面的一个例子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
Run Code Online (Sandbox Code Playgroud)

这些可以直接调用,就像它们是常规方法一样:

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.
Run Code Online (Sandbox Code Playgroud)

  • 我不明白这个答案。在他的示例中,他希望内联声明新的XElement(“ Prefix”,prefix =&gt; newPrefix)。所有这些答案等同于声明一个新功能。为什么不仅仅声明一个新函数呢? (3认同)
  • 因为: 1. 理解方法读取内联函数的逻辑比搜索不同的声明要容易得多 2. 经常使用内联函数时需要编写更少的代码 (3认同)

Ray*_*her 23

您的问题的答案是肯定而不是,取决于您对"内联函数"的含义.如果您正在使用C++开发中使用的术语,那么答案是否定的,您不能这样做 - 即使lambda表达式是一个函数调用.虽然您可以定义内联lambda表达式来替换C#中的函数声明,但编译器仍然最终会创建一个匿名函数.

这是我用来测试它的一些非常简单的代码(VS2015):

    static void Main(string[] args)
    {
        Func<int, int> incr = a => a + 1;
        Console.WriteLine($"P1 = {incr(5)}");
    }
Run Code Online (Sandbox Code Playgroud)

编译器生成什么?我使用了一个名为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
Run Code Online (Sandbox Code Playgroud)

看那些行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'
Run Code Online (Sandbox Code Playgroud)

这是一个非常短的功能,但它是一个功能.

这值得优化吗?罗.也许如果你每秒调用它数千次,但如果性能如此重要,那么你应该考虑调用用C/C++编写的本机代码来完成工作.

根据我的经验,可读性和可维护性几乎总是比优化速度增加几微秒更重要.使用函数使代码可读并控制变量作用域,而不用担心性能.

"过早优化是编程中所有邪恶(或至少大部分)的根源." - 唐纳德克努特

"一个无法正常运行的程序不需要快速运行" - 我

  • 这是 Google 热门的内联 C# 函数。你说“也许如果你每秒调用它数千次”,你猜怎么着 - 我每秒调用它 400 万次,所以是的......内联可能会很有用(并且大大提高代码可读性我要做的就是:在 16 个位置手动展开一个函数)。 (5认同)

Dal*_*oft 23

C#7增加了对本地功能的支持

以下是使用本地函数的上一个示例

void Method()
{
    string localFunction(string source)
    {
        // add your functionality here
        return source ;
    };

   // call the inline function
   localFunction("prefix");
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,在此示例中执行“string localFunction(string source) =&gt; source;”阅读[部分](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs /local-functions)关于明确赋值和变量捕获,这应该可以回答您的问题。 (2认同)
  • @qqqqqq c# 是静态类型的,因此 localfunction 只创建一次:在编译时。对于 Javascript,这将是一个不同的故事......每次调用 Method() 函数时都会创建该函数。 (2认同)

SLa*_*aks 16

是.

您可以创建匿名方法lambda表达式:

Func<string, string> PrefixTrimmer = delegate(string x) {
    return x ?? "";
};
Func<string, string> PrefixTrimmer = x => x ?? "";
Run Code Online (Sandbox Code Playgroud)

  • @Joe:`x ?? ""是null-coalescing运算符.http://msdn.microsoft.com/en-us/library/ms173224.aspx (2认同)
  • @Hellfrost:阅读问题。他不是在问 C++ 风格的内联函数。我不想创建函数,因为这些函数对我程序的任何其他部分没有任何帮助,但是这个 (2认同)

Hom*_*mam 5

您可以使用Func封装一个具有一个参数的方法,并返回由TResult参数指定的类型的值.

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


    // call the inline function
   inlineFunction("prefix");
}
Run Code Online (Sandbox Code Playgroud)


Dee*_*hra 5

不仅是内部方法,它还可以在类内部使用。

class Calculator
    {
        public static int Sum(int x,int y) => x + y;
        public static Func<int, int, int>  Add = (x, y) => x + y;
        public static Action<int,int> DisplaySum = (x, y) => Console.WriteLine(x + y);
    }
Run Code Online (Sandbox Code Playgroud)