我正在使用Linq To XML
new XElement("Prefix", Prefix == null ? "" : Prefix)
但我想在将前缀添加到xml之前对其进行一些计算,例如消除空格,特殊字符,进行一些计算等
我不想创建函数,因为这些函数对程序的任何其他部分都没有帮助,但是这有什么办法创建内联函数吗?
我正在使用Linq To XML
new XElement("Prefix", Prefix == null ? "" : Prefix)
但我想在将前缀添加到xml之前对其进行一些计算,例如消除空格,特殊字符,进行一些计算等
我不想创建函数,因为这些函数对程序的任何其他部分都没有帮助,但是这有什么办法创建内联函数吗?
Answers:
是的,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!");
}
Lambda是C#3.0中的新功能,有两种形式。
表达式lambdas:
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
声明lambda:
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的返回值,但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
这些可以直接调用,就像它们是常规方法一样:
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.
问题的答案是“是”和“否”,具体取决于您所说的“内联函数”的含义。如果您使用的术语类似于在C ++开发中使用的术语,那么答案是否定的,您不能这样做-即使是lambda表达式也是函数调用。确实可以定义内联lambda表达式来替换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 ++编写的本机代码来完成工作。
以我的经验,可读性和可维护性几乎总是比优化几微秒的速度更重要。使用函数使您的代码可读并控制变量作用域,而不必担心性能。
“过早的优化是编程中所有邪恶(或至少是大多数邪恶)的根源。” -唐纳德·努斯
“无法正常运行的程序不需要快速运行”-我
codeFunc <string,string> PrefixTrimmer = x => x ???“”; code我是新来的人,我真的不太了解MSDN文档
x ?? ""是null运算符。 msdn.microsoft.com/zh-CN/library/ms173224.aspx
x => (something),x是一个参数,并且(something)是返回值`。
不仅内部方法,它也可以在类内部使用。
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);
}