C#で「インライン関数」をどのように実行しますか?私はその概念を理解していないと思います。彼らは匿名メソッドのようですか?ラムダ関数は好きですか?
注:回答は、ほぼ完全に関数をインライン化する機能を扱っています。つまり、「関数呼び出しサイトを呼び出し先の本文で置き換える手動またはコンパイラの最適化」です。匿名(別名ラムダ)関数に興味がある場合は、@ jalfの回答を参照してください。または、誰もが話し続けている「ラムダ」とは何ですか?。
C#で「インライン関数」をどのように実行しますか?私はその概念を理解していないと思います。彼らは匿名メソッドのようですか?ラムダ関数は好きですか?
注:回答は、ほぼ完全に関数をインライン化する機能を扱っています。つまり、「関数呼び出しサイトを呼び出し先の本文で置き換える手動またはコンパイラの最適化」です。匿名(別名ラムダ)関数に興味がある場合は、@ jalfの回答を参照してください。または、誰もが話し続けている「ラムダ」とは何ですか?。
回答:
最後に.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(...)
1。以前は「力」が使用されていました。いくつかの反対投票があったので、用語を明確にするように努めます。コメントとドキュメントのように、The method should be inlined if possible.
特にMono(開いている)を考慮すると、インライン化またはより一般的なもの(仮想関数など)を考慮すると、いくつかのモノ固有の技術的な制限があります。全体として、はい、これはコンパイラーへのヒントですが、私はそれが求められたものだと思います。
インラインメソッドは、関数のコードが呼び出し元にロールインされるコンパイラ最適化にすぎません。
C#でこれを行うためのメカニズムはなく、それらがサポートされている言語では控えめに使用する必要があります。どこかで使用する必要がある理由がわからない場合は、使用しないでください。
編集:明確にするために、それらを慎重に使用する必要がある2つの主な理由があります。
何もせずに、コンパイラーに処理を任せ、インライン化が最適なソリューションであるかどうかをプロファイルして把握するのが最善です。もちろん、インライン化することに意味のあるものもありますが(特に数学演算子)、コンパイラーにそれを処理させることは、通常、ベストプラクティスです。
アップデート:パーkonrad.kruczynskiの答えは、以下では、.NETのバージョンアップへと4.0を含むため、真です。
MethodImplAttributeクラスを使用して、メソッドがインライン化されないようにすることができます...
[MethodImpl(MethodImplOptions.NoInlining)]
void SomeMethod()
{
// ...
}
...しかし、反対のことをして、それを強制的にインライン化する方法はありません。
GetExecutingAssembly
そしてGetCallingAssembly
メソッドがインライン化されているかどうかに応じて、異なる結果を与えることができます。メソッドをインライン化しないように強制すると、不確実性がなくなります。
あなたは2つの別々の概念を混同しています。関数のインライン化は、セマンティクスに影響を与えないコンパイラー最適化です。関数は、インライン化されているかどうかにかかわらず、同じように動作します。
一方、ラムダ関数は純粋に意味論的な概念です。言語仕様に定められた動作に従う限り、実装または実行方法に関する要件はありません。JITコンパイラーが適切であると感じる場合はインライン化でき、そうでない場合はインライン化できません。
C#にはインラインキーワードはありません。これは、特にJIT化された言語では、通常コンパイラーに任せることができる最適化であるためです。JITコンパイラーはランタイム統計にアクセスできるため、コードを記述する場合よりもはるかに効率的にインライン化するものを決定できます。コンパイラーが決定した場合、関数はインライン化されますが、どちらの方法でもそれを実行することはできません。:)
C ++の意味でのインライン関数ですか?通常の関数の内容は、コールサイトに自動的にインラインでコピーされますか?最終的には、関数の呼び出し時に関数呼び出しが実際には発生しません。
例:
inline int Add(int left, int right) { return left + right; }
もしそうなら、いいえ、これに相当するC#はありません。
または、別の関数内で宣言された関数を意味しますか?そうであれば、はい、C#は匿名メソッドまたはラムダ式を介してこれをサポートします。
例:
static void Example() {
Func<int,int,int> add = (x,y) => x + y;
var result = add(4,6); // 10
}
コーディはそれを正しく理解していますが、インライン関数とは何かの例を提供したいと思います。
次のコードがあるとします。
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()が呼び出された場合でも、これが行われる場合があることに注意してください。
インライン化される可能性が高いシナリオを表示するように編集されました。
はいまさに、唯一の違いは、値を返すという事実です。
簡略化(式を使用しない):
List<T>.ForEach
アクションを実行しますが、戻り結果を期待していません。
したがって、Action<T>
デリゲートで十分です。
List<T>.ForEach(param => Console.WriteLine(param));
言うことと同じです:
List<T>.ForEach(delegate(T param) { Console.WriteLine(param); });
違いは、paramの型とデリゲートのdeclerationが使用法によって推論され、中かっこが単純なインラインメソッドで必要とされないことです。
どこに
List<T>.Where
結果を期待して関数を受け取ります。
だから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();
または
Function<object, string> myFunction = theObject => theObject.ToString();
string myString = myFunction(someObject);
これがお役に立てば幸いです。
コードを強制的にインライン化したい場合があります。
たとえば、非常に反復的なブロック内で多数の決定が行われる複雑なルーチンがあり、それらの決定の結果、実行されるアクションは類似しているがわずかに異なる場合などです。たとえば、複雑な(非DB駆動の)並べ替え比較演算子を考えます。並べ替えアルゴリズムは、高速言語の文法的および意味的基準に従って単語を並べ替えている場合など、関連のないさまざまな基準に従って要素を並べ替えます。認識システム。ソースコードの可読性とモジュール性を維持するために、これらのアクションを処理するヘルパー関数を作成する傾向があります。
これらのヘルパー関数はインライン化する必要があることを知っています。これは、人間が理解する必要がなかった場合にコードが記述される方法だからです。この場合、関数呼び出しのオーバーヘッドがないことを確認したいと思います。
「これらのものをそのままにして、コンパイラーに処理を任せるのが最善です」(Cody Brocious)の文は、完全に愚かです。私は20年間高性能ゲームコードをプログラミングしてきましたが、インライン化する必要があるコード(関数)かどうかを知るのに「十分にスマート」なコンパイラーにまだ出会っていません。C#に「インライン」ステートメントがあると便利ですが、実際には、コンパイラは、「インライン」ヒントなしで常にインライン化するかどうかを判断するために必要なすべての情報を持っているわけではありません。関数が小さい(アクセサ)場合は、自動的にインライン化される可能性がありますが、数行のコードの場合はどうでしょうか。ナンセンス、コンパイラは知る方法がなく、最適化されたコード(アルゴリズム以外)をコンパイラに任せることはできません。
この質問はC#に関するものです。ただし、F#を使用すると、.NETでインライン関数を記述できます。参照:F#での `inline`の使用
アセンブリがngen-edになる場合は、TargetedPatchingOptOutを確認することをお勧めします。これは、ngenがメソッドをインライン化するかどうかを決定するのに役立ちます。MSDNリファレンス
ただし、最適化するのは宣言的なヒントであり、命令的なコマンドではありません。
ラムダ式はインライン関数です!C#には、インラインなどの追加の属性がないと思います。