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

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


当前回答

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

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

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

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

其他回答

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

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

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

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

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

最后,在。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的技术限制。总的来说,是的,这是对编译器的一个提示,但我猜这是要求的。

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
}

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(),它也可能这样做。

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