你如何在C#中做"内联函数"?我认为我不理解这个概念.他们喜欢匿名方法吗?像lambda函数?
注意:答案几乎完全处理内联函数的能力,即"用被调用者的主体替换函数调用站点的手动或编译器优化".如果您对匿名(也称为lambda)函数感兴趣,请参阅@ jalf的答案或者每个人都在说什么'Lambda'?.
最后在.NET 4.5中,CLR允许使用值提示/建议1方法内联MethodImplOptions.AggressiveInlining
.它也可以在Mono的后备箱中使用(今天提交).
// The full attribute usage is in mscorlib.dll, // so should not need to include extra references using System.Runtime.CompilerServices; ... [MethodImpl(MethodImplOptions.AggressiveInlining)] void MyMethod(...)
1.此前使用的是"force".由于有一些downvotes,我会试着澄清这个词.正如在评论和文档中一样,The method should be inlined if possible.
特别是考虑到Mono(开放),考虑内联或更普遍的(如虚拟功能),存在一些特定于单一的技术限制.总的来说,是的,这是对编译器的暗示,但我想这就是要求的.
内联方法只是一种编译器优化,其中函数的代码被卷入调用者.
在C#中没有任何机制可以做到这一点,并且它们在支持它们的语言中被谨慎使用 - 如果你不知道为什么它们应该被用在某个地方,它们就不应该被使用.
编辑:为了澄清,有两个主要原因需要谨慎使用:
在没有必要的情况下,通过内联使用大量二进制文件很容易
从性能的角度来看,编译器往往比你应该知道更好
最好不要管它,让编译器完成它的工作,然后分析并确定内联是否是最适合你的解决方案.当然,有些事情是有意义的内联(特别是数学运算符),但让编译器处理它通常是最好的做法.
更新:根据konrad.kruczynski的回答,以下版本适用于4.0及以下版本的.NET.
您可以使用MethodImplAttribute类来防止方法被内联...
[MethodImpl(MethodImplOptions.NoInlining)] void SomeMethod() { // ... }
...但是没有办法做相反的事情并强迫它被内联.
你混合了两个不同的概念.函数内联是一种编译器优化,它对语义没有影响.无论内联与否,函数的行为都相同.
另一方面,lambda函数纯粹是一个语义概念.只要它们遵循语言规范中规定的行为,就不需要如何实现或执行它们.如果JIT编译器感觉如此,则可以内联它们,如果不是,则可以内联它们.
C#中没有内联关键字,因为它是一种优化,通常可以留给编译器,特别是在JIT的语言中.JIT编译器可以访问运行时统计信息,这使得它可以比编写代码时更有效地决定内联内容.如果编译器决定使用函数,那么无论如何都无法对它进行任何操作.:)
你的意思是C++意义上的内联函数吗?其中普通函数的内容是否自动内嵌到调用点?最终结果是在调用函数时实际上没有发生函数调用.
例:
inline int Add(int left, int right) { return left + right; }
如果是,那么不,没有C#等同于此.
或者你的意思是在另一个函数中声明的函数?如果是,那么是的,C#通过匿名方法或lambda表达式支持这一点.
例:
static void Example() { Funcadd = (x,y) => x + y; var result = add(4,6); // 10 }
Cody说得对,但我想提供一个内联函数的例子.
假设你有这个代码:
private void OutputItem(string x) { Console.WriteLine(x); //maybe encapsulate additional logic to decide // whether to also write the message to Trace or a log file } public IListBuildListAndOutput(IEnumerable x) { // let's pretend IEnumerable .ToList() doesn't exist for the moment IList result = new List (); foreach(string y in x) { result.Add(y); OutputItem(y); } return result; }
该编译器刚刚在优化器可以选择修改密码,以避免重复在堆栈上放置到OutputItem()的调用,因此,这将是,如果你已经写成这样的代码:
public IListBuildListAndOutput(IEnumerable x) { IList result = new List (); foreach(string y in x) { result.Add(y); // full OutputItem() implementation is placed here Console.WriteLine(y); } return result; }
在这种情况下,我们会说OutputItem()函数是内联的.请注意,即使从其他位置调用OutputItem(),它也可能会这样做.
编辑以显示更可能被内联的场景.
是的,唯一的区别是它返回一个值.
简化(不使用表达式):
List
采取行动,它不期望返回结果.
所以Action
代表就够了..说:
List.ForEach(param => Console.WriteLine(param));
和说:
List.ForEach(delegate(T param) { Console.WriteLine(param); });
区别在于param类型和委托decleration是由用法推断的,并且在简单的内联方法中不需要括号.
在哪里
List
采取功能,期待结果.
所以Function
我们期待:
List.Where(param => param.Value == SomeExpectedComparison);
这与:
List.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
您还可以内联声明这些方法并将它们与变量IE一起对齐:
Action myAction = () => Console.WriteLine("I'm doing something Nifty!"); myAction();
要么
Function
我希望这有帮助.