C#中的内联函数?
你如何做C#中的“内联函数”? 我不认为我理解这个概念。 他们喜欢匿名方法吗? 像lambda函数?
注意 :答案几乎完全处理内联函数的能力,即“手动或编译器优化,用被调用者的主体replace函数调用站点”。 如果您对匿名(aka lambda)函数感兴趣,请参阅@ jalf的答案或每个人都在说的“Lambda”是什么? 。
最后在.NET 4.5中,CLR允许使用MethodImplOptions.AggressiveInlining
值提示/build议1方法内联。 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 。 以前“力量”在这里使用。 由于有一些降薪,我会尽力澄清这个词。 正如在注释和文档中一样, The method should be inlined if possible.
, The method should be inlined if possible.
特别是考虑到Mono(开放的),考虑内联或者更一般的(比如虚拟函数),存在一些单一特定的技术限制。 总的来说,是的,这是编译器的一个提示,但我想这就是要求的。
内联方法只是一个编译器优化,其中函数的代码被放入调用方。
在C#中没有这样做的机制,它们将被谨慎地用在支持它们的语言中 – 如果你不知道为什么它们应该用在某个地方,那它们就不应该是这样。
编辑:澄清,他们需要谨慎使用有两个主要原因:
- 在没有必要的情况下使用内联来制作大量的二进制代码是很容易的
- 从性能的angular度来看,编译器倾向于比内存更好
最好是让事情独立,并让编译器完成工作,然后进行configuration并确定内联是否是最适合您的解决scheme。 当然,有些内容是有意义的(特别是math运算符),但让编译器处理它通常是最好的做法。
更新:根据konrad.kruczynski的回答 ,以下版本的.NET版本到4.0版本都是如此。
您可以使用MethodImplAttribute类来防止方法被内联…
[MethodImpl(MethodImplOptions.NoInlining)] void SomeMethod() { // ... }
…但是没有办法做相反的事, 强迫它被内联。
你在混合两个单独的概念。 函数内联是对语义没有影响的编译器优化。 无论是否内联,函数的行为都是相同的。
另一方面,lambda函数纯粹是一个语义概念。 只要遵循语言规范中规定的行为,就没有要求如何实施或执行它们。 如果JIT编译器有这种感觉,可以将它们内联,或者如果不是这样,则可以不内联。
在C#中没有内联关键字,因为它是一个优化,通常可以留给编译器,特别是在JIT的语言。 JIT编译器可以访问运行时统计信息,使其能够比编写代码时更有效地决定内联。 如果编译器决定了,函数将被内联,而且无论哪种方式都无法做到。 🙂
你是指C ++意义上的内联函数吗? 其中正常function的内容自动复制到内部的callsite? 最终效果是调用一个函数时实际上没有函数调用。
例:
inline int Add(int left, int right) { return left + right; }
如果是这样,那么不,没有相当于这个C#。
或者你的意思是在另一个函数中声明的函数? 如果是这样,那么C#通过匿名方法或lambdaexpression式支持。
例:
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; }
编译器 Just-In-Time优化器可以select修改代码,以避免重复将一个对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(),也可能会这样做。
编辑以显示更可能被内联的情景。
是的确实,唯一的区别是它返回一个值。
简化(不使用expression式):
List<T>.ForEach
一个动作,它不期望返回结果。
所以一个Action<T>
委托就足够了。说:
List<T>.ForEach(param => Console.WriteLine(param));
也是一样的说:
List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });
区别在于paramtypes和delegate decleration是通过使用推断出来的,并且一个简单的内联方法不需要大括号。
在哪里
List<T>.Where
取一个函数,期待一个结果。
所以一个Function<T, bool>
将是预期的:
List<T>.Where(param => param.Value == SomeExpectedComparison);
这是一样的:
List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
你也可以声明这些内联方法,并将它们赋给variablesIE:
Action myAction = () => Console.WriteLine("I'm doing something Nifty!"); myAction();
要么
Function<object, string> myFunction = theObject => theObject.ToString(); string myString = myFunction(someObject);
我希望这有帮助。
有些情况下我希望强制代码被内联。
例如,如果我有一个复杂的例程,在一个高度迭代的块中有大量的决策,那么这些决策会导致类似的但稍微不同的行为。 例如,考虑一个复杂的(非数据库驱动的)sorting比较器,其中sortingalgorithm根据许多不相关的不相关标准对元素进行sorting,例如,如果他们根据语法和快速语言的语义标准识别系统。 我倾向于编写帮助函数来处理这些操作,以保持源代码的可读性和模块性。
我知道那些辅助函数应该是内联的,因为如果代码从来不需要被人理解,那么代码将被编写。 我当然希望确保在这种情况下,没有函数调用开销。
声明“最好把这些东西放在一边,让编译器去做这个工作..”(Cody Brocious)是完全的垃圾。 我已经编写了20年的高性能游戏代码,而且我还没有遇到一个“足够聪明”的编译器来知道哪些代码应该被内联(函数)或不是。 在c#中有一个“inline”语句是很有用的,事实上编译器并没有提供所有的信息来确定哪个函数应该总是内联或者没有内联的提示。 当然,如果函数很小(访问者),那么它可能会自动内联,但如果是几行代码呢? 无意义的是,编译器没有办法知道,你不能把它留给编译器来优化代码(algorithm之外)。
不,C#中没有这样的构造,但.NET JIT编译器可以决定在JIT时间内执行内联函数调用。 但我其实不知道是否真的在做这种优化。
(我认为应该:-))
万一你的程序集会被修改,你可能想看看TargetedPatchingOptOut。 这将有助于ngen决定是否内联方法。 MSDN参考
尽pipe如此,这仍然只是一个说明性的提示,而不是一个命令性的命令。
我知道这个问题是关于C#的。 但是,您可以使用F#在.NET中编写内联函数。 请参阅: 在F#中使用`inline`
我有一个方法,如果在debugging模式下运行,返回true / false。 如果在debugging模式下,我有几个安全检查被绕过。
我想内联这个调用,因为如果我有十几个地方检查debugging模式,那么通过强迫某人覆盖全部12个地方而不是仅仅用一个方法就可以绕过。
现在说实话,我不知道编译器是否已经内联了。 尽pipe强迫它这样做会很好。
也许当我们移动到4.5我猜…
C#不支持像python这样的dynamic语言的内联方法(或函数)。 然而,匿名方法和lambdas可以用于类似的目的,包括当你需要访问包含方法中的variables,如下面的例子。
static void Main(string[] args) { int a = 1; Action inline = () => a++; inline(); //here a = 2 }
Lambdaexpression式是内联函数! 我认为,C#没有像内联或类似的额外的属性!