如何在c#中做“内联函数”?我想我不明白这个概念。它们像匿名方法吗?比如函数?

注意:答案几乎完全涉及内联函数的能力,即。用被调用者的主体替换函数调用站点的手册或编译器优化。如果你对匿名(又名lambda)函数感兴趣,请参阅@jalf的回答或每个人都在谈论的“lambda”是什么?


内联方法只是一种编译器优化,将函数的代码滚入调用方。

在c#中没有这样做的机制,在支持它们的语言中应该谨慎使用它们——如果你不知道为什么应该在某个地方使用它们,那么就不应该使用它们。

编辑:要澄清的是,有两个主要原因需要谨慎使用:

在不必要的情况下使用内联可以很容易地生成大量二进制文件 从性能的角度来看,编译器往往比您更了解什么时候应该内联

最好不去管它,让编译器完成它的工作,然后进行分析并确定内联是否是最适合您的解决方案。当然,有些东西内联是有意义的(特别是数学运算符),但让编译器处理通常是最佳实践。


Lambda表达式是内联函数!我认为,c#没有额外的属性,比如内联或类似的东西!


你是指c++意义上的内联函数吗?其中一个正常函数的内容被自动内联复制到callsite?最终的结果是,在调用函数时实际上不会发生函数调用。

例子:

inline int Add(int left, int right) { return left + right; }

如果是,那么没有,c#中没有与之等价的东西。

或者你是指在另一个函数中声明的函数吗?如果是的话,c#通过匿名方法或lambda表达式来支持。

例子:

static void Example() {
  Func<int,int,int> add = (x,y) => x + y;
  var result = add(4,6);  // 10
}

没错,唯一的区别是它返回一个值。

简化(不使用表达式):

列表> < T。ForEach执行一个操作,它不期望返回结果。

所以Action<T>委托就足够了。说:

List<T>.ForEach(param => Console.WriteLine(param));

就等于说:

List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });

不同之处在于参数类型和委托声明是根据用法推断的,在简单的内联方法上不需要花括号。

列表> < T。接受一个函数,期待一个结果。

因此,一个Function<T, bool>将被期望:

List<T>.Where(param => param.Value == SomeExpectedComparison);

也就是:

List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });

你也可以内联声明这些方法,并将它们赋值给变量IE:

Action myAction = () => Console.WriteLine("I'm doing something Nifty!");

myAction();

or

Function<object, string> myFunction = theObject => theObject.ToString();

string myString = myFunction(someObject);

我希望这能有所帮助。


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 IList<string> BuildListAndOutput(IEnumerable<string> x)
{  // let's pretend IEnumerable<T>.ToList() doesn't exist for the moment
    IList<string> result = new List<string>();

    foreach(string y in x)
    {
        result.Add(y);
        OutputItem(y);
    }
    return result;
}

编译器即时优化器可以选择修改代码,以避免在堆栈上重复调用OutputItem(),这样就好像你写的代码是这样的:

public IList<string> BuildListAndOutput(IEnumerable<string> x)
{
    IList<string> result = new List<string>();

    foreach(string y in x)
    {
        result.Add(y);

        // full OutputItem() implementation is placed here
        Console.WriteLine(y);   
    }

    return result;
}

在本例中,我们可以说OutputItem()函数是内联的。注意,即使从其他地方也调用OutputItem(),它也可能这样做。

经过编辑以显示更可能内联的场景。


你把两个不同的概念混在一起了。函数内联是对语义没有影响的编译器优化。不管函数是否内联,它的行为都是一样的。

另一方面,lambda函数纯粹是一个语义概念。对于它们应该如何实现或执行没有要求,只要它们遵循语言规范中规定的行为即可。如果JIT编译器喜欢,它们可以内联,如果不喜欢,则不可以。

c#中没有内联关键字,因为这是一种通常可以留给编译器的优化,尤其是在JIT语言中。JIT编译器可以访问运行时统计信息,这使它能够比编写代码时更有效地决定内联哪些内容。函数将内联,如果编译器决定,没有什么你可以做的任何方式。:)


不,c#中没有这样的构造,但是. net JIT编译器可以决定在JIT时间执行内联函数调用。但我实际上不知道它是否真的在做这样的优化。 (我认为它应该:))


更新:根据konrad.kruczynski的回答,以下情况适用于。net 4.0及以下版本。

你可以使用MethodImplAttribute类来防止一个方法被内联…

[MethodImpl(MethodImplOptions.NoInlining)]
void SomeMethod()
{
    // ...
}

...但是没有办法做相反的事情,强迫它内联。


在某些情况下,我确实希望强制代码内联。

For example if I have a complex routine where there are a large number of decisions made within a highly iterative block and those decisions result in similar but slightly differing actions to be carried out. Consider for example, a complex (non DB driven) sort comparer where the sorting algorythm sorts the elements according to a number of different unrelated criteria such as one might do if they were sorting words according to gramatical as well as semantic criteria for a fast language recognition system. I would tend to write helper functions to handle those actions in order to maintain the readability and modularity of the source code.

我知道那些辅助函数应该是内联的,因为这是编写代码的方式,如果它永远不需要被人类理解的话。在这种情况下,我当然希望确保没有函数调用开销。


The statement "its best to leave these things alone and let the compiler do the work.." (Cody Brocious) is complete rubish. I have been programming high performance game code for 20 years, and I have yet to come across a compiler that is 'smart enough' to know which code should be inlined (functions) or not. It would be useful to have a "inline" statement in c#, truth is that the compiler just doesnt have all the information it needs to determine which function should be always inlined or not without the "inline" hint. Sure if the function is small (accessor) then it might be automatically inlined, but what if it is a few lines of code? Nonesense, the compiler has no way of knowing, you cant just leave that up to the compiler for optimized code (beyond algorithims).


如果您的程序集将被ngen-ed,您可能想要查看TargetedPatchingOptOut。这将帮助ngen决定是否内联方法。MSDN参考

这仍然只是一个声明性的优化提示,而不是命令式命令。


最后,在。net 4.5中,CLR允许使用MethodImplOptions提示/suggest1方法内联。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”。我会试着解释一下这个术语。正如注释和文档中所述,如果可能的话,方法应该内联。特别是考虑到Mono(它是开放的),在考虑内联或更一般的技术(如虚函数)时,有一些特定于Mono的技术限制。总的来说,是的,这是对编译器的一个提示,但我猜这是要求的。


我知道这个问题是关于c#的。然而,你可以用f#在。net中编写内联函数。参见:在f#中使用' inline '