简体   繁体   English

C# 中的内联函数?

[英]Inline functions in C#?

How do you do "inline functions" in C#?你如何在 C# 中执行“内联函数”? I don't think I understand the concept.我不认为我理解这个概念。 Are they like anonymous methods?它们像匿名方法吗? Like lambda functions?像 lambda 功能?

Note : The answers almost entirely deal with the ability to inline functions , ie "a manual or compiler optimization that replaces a function call site with the body of the callee."注意:答案几乎完全涉及内联函数的能力,即“用被调用者的主体替换 function 调用站点的手动或编译器优化”。 If you are interested in anonymous (aka lambda) functions , see @jalf's answer or What is this 'Lambda' everyone keeps speaking of?如果您对匿名(又名 lambda)函数感兴趣,请参阅@jalf 的回答每个人都在谈论的“Lambda”是什么? . .

Finally in .NET 4.5, the CLR allows one to hint/suggest 1 method inlining using MethodImplOptions.AggressiveInlining value.最后,在 .NET 4.5 中,CLR 允许使用MethodImplOptions.AggressiveInlining值提示/建议1 个方法内联。 It is also available in the Mono's trunk (committed today).它也可以在 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 . 1 . Previously "force" was used here.以前在这里使用“力”。 Since there were a few downvotes, I'll try to clarify the term.由于有一些反对票,我将尝试澄清该术语。 As in the comments and the documentation, The method should be inlined if possible.正如在评论和文档中一样, The method should be inlined if possible.The method should be inlined if possible. Especially considering Mono (which is open), there are some mono-specific technical limitations considering inlining or more general one (like virtual functions).特别是考虑到 Mono(它是开放的),考虑到内联或更通用的技术限制(例如虚函数),存在一些特定于 Mono 的技术限制。 Overall, yes, this is a hint to compiler, but I guess that is what was asked for.总的来说,是的,这是对编译器的一个提示,但我想这就是所要求的。

Inline methods are simply a compiler optimization where the code of a function is rolled into the caller.内联方法只是一种编译器优化,其中函数的代码被滚动到调用者中。

There's no mechanism by which to do this in C#, and they're to be used sparingly in languages where they are supported -- if you don't know why they should be used somewhere, they shouldn't be.在 C# 中没有执行此操作的机制,并且在支持它们的语言中应谨慎使用它们——如果您不知道为什么应该在某处使用它们,那么它们就不应该使用。

Edit: To clarify, there are two major reasons they need to be used sparingly:编辑:为了澄清,有两个主要原因需要谨慎使用它们:

  1. It's easy to make massive binaries by using inline in cases where it's not necessary在不需要的情况下使用内联很容易制作大量二进制文件
  2. The compiler tends to know better than you do when something should, from a performance standpoint, be inlined从性能的角度来看,编译器往往比你更清楚什么时候应该内联

It's best to leave things alone and let the compiler do its work, then profile and figure out if inline is the best solution for you.最好不要管它,让编译器完成它的工作,然后分析并确定内联是否是最适合您的解决方案。 Of course, some things just make sense to be inlined (mathematical operators particularly), but letting the compiler handle it is typically the best practice.当然,有些事情内联才有意义(尤其是数学运算符),但让编译器处理它通常是最佳实践。

Update: Per konrad.kruczynski's answer , the following is true for versions of .NET up to and including 4.0.更新:根据konrad.kruczynski 的回答,以下适用于 .NET 版本(包括 4.0)。

You can use the MethodImplAttribute class to prevent a method from being inlined...您可以使用MethodImplAttribute 类防止方法被内联...

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

...but there is no way to do the opposite and force it to be inlined. ...但没有办法做相反的事情并强制它内联。

You're mixing up two separate concepts.你混淆了两个不同的概念。 Function inlining is a compiler optimization which has no impact on the semantics.函数内联是一种编译器优化,对语义没有影响。 A function behaves the same whether it's inlined or not.无论是否内联,函数的行为都是相同的。

On the other hand, lambda functions are purely a semantic concept.另一方面,lambda 函数纯粹是一个语义概念。 There is no requirement on how they should be implemented or executed, as long as they follow the behavior set out in the language spec.对它们应该如何实现或执行没有要求,只要它们遵循语言规范中规定的行为。 They can be inlined if the JIT compiler feels like it, or not if it doesn't.如果 JIT 编译器喜欢,它们可以被内联,如果不喜欢,则不可以。

There is no inline keyword in C#, because it's an optimization that can usually be left to the compiler, especially in JIT'ed languages. C# 中没有 inline 关键字,因为它是一种通常可以留给编译器的优化,尤其是在 JIT 语言中。 The JIT compiler has access to runtime statistics which enables it to decide what to inline much more efficiently than you can when writing the code. JIT 编译器可以访问运行时统计信息,这使它能够比编写代码时更有效地决定要内联的内容。 A function will be inlined if the compiler decides to, and there's nothing you can do about it either way.如果编译器决定内联一个函数,那么无论哪种方式你都无能为力。 :) :)

Cody has it right, but I want to provide an example of what an inline function is.科迪说得对,但我想提供一个内联函数是什么的例子。

Let's say you have this code:假设您有以下代码:

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;
}

The compiler Just-In-Time optimizer could choose to alter the code to avoid repeatedly placing a call to OutputItem() on the stack, so that it would be as if you had written the code like this instead: 编译器 即时优化器可以选择更改代码,以避免在堆栈上重复调用 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;
}

In this case, we would say the OutputItem() function was inlined.在这种情况下,我们会说 OutputItem() 函数是内联的。 Note that it might do this even if the OutputItem() is called from other places as well.请注意,即使 OutputItem() 也从其他地方调用,它也可能会这样做。

Edited to show a scenario more-likely to be inlined.编辑以显示更可能被内联的场景。

Do you mean inline functions in the C++ sense?你是说 C++ 意义上的内联函数吗? In which the contents of a normal function are automatically copied inline into the callsite?其中普通函数的内容会自动内联复制到调用站点中? The end effect being that no function call actually happens when calling a function.最终效果是在调用函数时实际上没有发生函数调用。

Example:例子:

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

If so then no, there is no C# equivalent to this.如果是,则不,没有与此等效的 C#。

Or Do you mean functions that are declared within another function?或者你的意思是在另一个函数中声明的函数? If so then yes, C# supports this via anonymous methods or lambda expressions.如果是,则是,C# 通过匿名方法或 lambda 表达式支持这一点。

Example:例子:

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

Yes Exactly, the only distinction is the fact it returns a value.是的,唯一的区别是它返回一个值。

Simplification (not using expressions):简化(不使用表达式):

List<T>.ForEach Takes an action, it doesn't expect a return result. List<T>.ForEach一个动作,它不期望返回结果。

So an Action<T> delegate would suffice.. say:所以Action<T>委托就足够了..说:

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

is the same as saying:等同于说:

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

the difference is that the param type and delegate decleration are inferred by usage and the braces aren't required on a simple inline method.不同之处在于参数类型和委托声明是通过使用推断的,并且简单的内联方法不需要大括号。

Where as然而

List<T>.Where Takes a function, expecting a result. List<T>.Where一个函数,期待一个结果。

So an Function<T, bool> would be expected:所以一个Function<T, bool>应该是:

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

which is the same as:这与:

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

You can also declare these methods inline and asign them to variables IE:您还可以内联声明这些方法并将它们分配给变量 IE:

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

myAction();

or或者

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

string myString = myFunction(someObject);

I hope this helps.我希望这有帮助。

There are occasions where I do wish to force code to be in-lined.有时我确实希望强制代码内联。

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.例如,考虑一个复杂的(非 DB 驱动的)排序比较器,其中排序算法根据许多不同的不相关标准对元素进行排序,例如如果根据快速语言的语法和语义标准对单词进行排序,则可能会这样做识别系统。 I would tend to write helper functions to handle those actions in order to maintain the readability and modularity of the source code.我倾向于编写辅助函数来处理这些操作,以保持源代码的可读性和模块化。

I know that those helper functions should be in-lined because that is the way that the code would be written if it never had to be understood by a human.我知道这些辅助函数应该是内联的,因为如果代码永远不需要被人类理解,那么这就是编写代码的方式。 I would certainly want to ensure in this case that there were no function calling overhead.我当然想确保在这种情况下没有函数调用开销。

The statement "its best to leave these things alone and let the compiler do the work.." (Cody Brocious) is complete rubish.声明“最好不要管这些事情,让编译器完成工作......”(Cody Brocious)完全是垃圾。 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.我已经编写了 20 年的高性能游戏代码,但我还没有遇到一个“足够聪明”的编译器,可以知道哪些代码应该被内联(函数)。 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.在 c# 中有一个“内联”语句会很有用,事实是编译器没有它需要的所有信息来确定在没有“内联”提示的情况下应该始终内联或不内联哪个函数。 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).废话,编译器无法知道,你不能把它留给编译器来优化代码(超越算法)。

I know this question is about C#.我知道这个问题是关于 C# 的。 However, you can write inline functions in .NET with F#.但是,您可以使用 F# 在 .NET 中编写内联函数。 see: Use of `inline` in F#请参阅: 在 F# 中使用 `inline`

No, there is no such construct in C#, but the .NET JIT compiler could decide to do inline function calls on JIT time.不,C# 中没有这样的构造,但是 .NET JIT 编译器可以决定在 JIT 时间执行内联函数调用。 But i actually don't know if it is really doing such optimizations.但我实际上不知道它是否真的在做这样的优化。
(I think it should :-)) (我认为它应该:-))

In case your assemblies will be ngen-ed, you might want to take a look at TargetedPatchingOptOut.如果您的程序集将被生成,您可能需要查看 TargetedPatchingOptOut。 This will help ngen decide whether to inline methods.这将帮助 ngen 决定是否内联方法。 MSDN reference MSDN参考

It is still only a declarative hint to optimize though, not an imperative command.尽管如此,它仍然只是一个声明性的优化提示,而不是一个命令式命令。

Lambda expressions are inline functions! Lambda 表达式是内联函数! I think, that C# doesn`t have a extra attribute like inline or something like that!我认为,C# 没有像 inline 之类的额外属性!

C# does not support inline methods (or functions) in the way dynamic languages like python do. C# 不支持像 python 这样的动态语言那样的内联方法(或函数)。 However anonymous methods and lambdas can be used for similar purposes including when you need to access a variable in the containing method like in the example below.但是,匿名方法和 lambdas 可用于类似目的,包括当您需要访问包含方法中的变量时,如下例所示。

static void Main(string[] args)
{
    int a = 1;

    Action inline = () => a++;
    inline();
    //here a = 2
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM