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

我正在使用Linq To XML

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

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

我不想创build函数,因为这不会对我的程序的任何其他部分有任何帮助,但是,这是否有任何方法来创build内联函数?

是的,C#支持。 有几种可用的语法:

  • 匿名方法 (可从C#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!"); } 
  • expression式Lambdas (可从C#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(可从C#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; }; 

基本上有两种不同的types: FuncAction 。 函数的返回值,但Action s不。 Func的最后一个types参数是返回types; 所有其他的都是参数types。

类似的types有不同的名字,但是声明它们的内联语法是一样的。 一个例子是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. 

是。

您可以创build匿名方法或lambdaexpression式 :

 Func<string, string> PrefixTrimmer = delegate(string x) { return x ?? ""; }; Func<string, string> PrefixTrimmer = x => x ?? ""; 

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

 void Method() { Func<string,string> inlineFunction = source => { // add your functionality here return source ; }; // call the inline function inlineFunction("prefix"); } 

你的问题的答案是肯定和否,取决于你的意思是“内联函数”。 如果您使用的术语像C ++开发中使用的那样,那么答案是否定的,您不能这样做 – 即使是lambdaexpression式也是一个函数调用。 尽pipe可以定义内联lambdaexpression式来replaceC#中的函数声明,但编译器仍然最终创build了一个匿名函数。

以下是我用来testing这个(VS2015)的一些非常简单的代码:

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

编译器生成什么? 我使用了一个称为ILSpy的漂亮工具,它显示了生成的实际IL组件。 看看(我省略了很多课程设置的东西)

这是主要function:

  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格式化并打印结果。

这里是所谓的function:

  .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' 

这是一个非常短的function,但它是一个function。

这是值得优化的任何努力? 罗。 也许如果你每秒钟调用它几千次,但是如果性能是非常重要的,那么你应该考虑调用用C / C ++编写的本地代码来完成这项工作。

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

“不成熟的优化是编程中所有邪恶(或者至less大部分)的根源。 Donald Knuth

“一个运行不正常的程序不需要跑得快” – 我