Din*_*nah 264 c# optimization inline
你如何在C#中做"内联函数"?我认为我不理解这个概念.他们喜欢匿名方法吗?像lambda函数?
注意:答案几乎完全处理内联函数的能力,即"用被调用者的主体替换函数调用站点的手动或编译器优化".如果您对匿名(也称为lambda)函数感兴趣,请参阅@ jalf的答案或者每个人都在说什么'Lambda'?.
kon*_*ski 371
最后在.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(...)
Run Code Online (Sandbox Code Playgroud)
1.此前使用的是"force".由于有一些downvotes,我会试着澄清这个词.正如在评论和文档中一样,The method should be inlined if possible.
特别是考虑到Mono(开放),考虑内联或更普遍的(如虚拟功能),存在一些特定于单一的技术限制.总的来说,是的,这是对编译器的暗示,但我想这就是要求的.
Cod*_*ous 85
内联方法只是一种编译器优化,其中函数的代码被卷入调用者.
在C#中没有任何机制可以做到这一点,并且它们在支持它们的语言中被谨慎使用 - 如果你不知道为什么它们应该被用在某个地方,它们就不应该被使用.
编辑:为了澄清,有两个主要原因需要谨慎使用:
最好不要管它,让编译器完成它的工作,然后分析并确定内联是否是最适合你的解决方案.当然,有些事情是有意义的内联(特别是数学运算符),但让编译器处理它通常是最好的做法.
BAC*_*CON 52
更新:根据konrad.kruczynski的回答,以下版本适用于4.0及以下版本的.NET.
您可以使用MethodImplAttribute类来防止方法被内联...
[MethodImpl(MethodImplOptions.NoInlining)]
void SomeMethod()
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
...但是没有办法做相反的事情并强迫它被内联.
jal*_*alf 33
你混合了两个不同的概念.函数内联是一种编译器优化,它对语义没有影响.无论内联与否,函数的行为都相同.
另一方面,lambda函数纯粹是一个语义概念.只要它们遵循语言规范中规定的行为,就不需要如何实现或执行它们.如果JIT编译器感觉如此,则可以内联它们,如果不是,则可以内联它们.
C#中没有内联关键字,因为它是一种优化,通常可以留给编译器,特别是在JIT的语言中.JIT编译器可以访问运行时统计信息,这使得它可以比编写代码时更有效地决定内联内容.如果编译器决定使用函数,那么无论如何都无法对它进行任何操作.:)
Jar*_*Par 21
你的意思是C++意义上的内联函数吗?其中普通函数的内容是否自动内嵌到调用点?最终结果是在调用函数时实际上没有发生函数调用.
例:
inline int Add(int left, int right) { return left + right; }
Run Code Online (Sandbox Code Playgroud)
如果是,那么不,没有C#等同于此.
或者你的意思是在另一个函数中声明的函数?如果是,那么是的,C#通过匿名方法或lambda表达式支持这一点.
例:
static void Example() {
Func<int,int,int> add = (x,y) => x + y;
var result = add(4,6); // 10
}
Run Code Online (Sandbox Code Playgroud)
Joe*_*orn 20
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;
}
Run Code Online (Sandbox Code Playgroud)
该编译器刚刚在优化器可以选择修改密码,以避免重复在堆栈上放置到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;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们会说OutputItem()函数是内联的.请注意,即使从其他位置调用OutputItem(),它也可能会这样做.
编辑以显示更可能被内联的场景.
是的,唯一的区别是它返回一个值.
简化(不使用表达式):
List<T>.ForEach
采取行动,它不期望返回结果.
所以Action<T>
代表就够了..说:
List<T>.ForEach(param => Console.WriteLine(param));
Run Code Online (Sandbox Code Playgroud)
和说:
List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });
Run Code Online (Sandbox Code Playgroud)
区别在于param类型和委托decleration是由用法推断的,并且在简单的内联方法中不需要括号.
在哪里
List<T>.Where
采取功能,期待结果.
所以Function<T, bool>
我们期待:
List<T>.Where(param => param.Value == SomeExpectedComparison);
Run Code Online (Sandbox Code Playgroud)
这与:
List<T>.Where(delegate(T param) { return param.Value == SomeExpectedComparison; });
Run Code Online (Sandbox Code Playgroud)
您还可以内联声明这些方法并将它们与变量IE一起对齐:
Action myAction = () => Console.WriteLine("I'm doing something Nifty!");
myAction();
Run Code Online (Sandbox Code Playgroud)
要么
Function<object, string> myFunction = theObject => theObject.ToString();
string myString = myFunction(someObject);
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助.
归档时间: |
|
查看次数: |
169856 次 |
最近记录: |