Linq ToXMLを使用しています
new XElement("Prefix", Prefix == null ? "" : Prefix)
しかし、スペース、特殊文字、いくつかの計算などを削除するなど、接頭辞をxmlに追加する前にいくつかの計算を行いたい
これは私のプログラムの他の部分では役に立たないので、関数を作成したくありませんが、これは、インライン関数を作成する方法はありますか?
Linq ToXMLを使用しています
new XElement("Prefix", Prefix == null ? "" : Prefix)
しかし、スペース、特殊文字、いくつかの計算などを削除するなど、接頭辞をxmlに追加する前にいくつかの計算を行いたい
これは私のプログラムの他の部分では役に立たないので、関数を作成したくありませんが、これは、インライン関数を作成する方法はありますか?
回答:
はい、C#はそれをサポートしています。利用可能な構文はいくつかあります。
匿名メソッドがC#2.0で追加されました。
Func<int, int, int> add = delegate(int x, int y)
{
return x + y;
};
Action<int> print = delegate(int x)
{
Console.WriteLine(x);
}
Action<int> helloWorld = delegate // parameters can be elided if ignored
{
Console.WriteLine("Hello world!");
}
ラムダはC#3.0の新機能であり、2つのフレーバーがあります。
式ラムダ:
Func<int, int, int> add = (int x, int y) => x + y; // or...
Func<int, int, int> add = (x, y) => x + y; // types are inferred by the compiler
ステートメントラムダ:
Action<int> print = (int x) => { Console.WriteLine(x); };
Action<int> print = x => { Console.WriteLine(x); }; // inferred types
Func<int, int, int> add = (x, y) => { return x + y; };
ローカル関数はC#7.0で導入されました。
int add(int x, int y) => x + y;
void print(int x) { Console.WriteLine(x); }
これらには基本的に2つの異なるタイプがあります:FuncとAction。Funcsは値を返しますが、Actionsは返しません。aの最後の型パラメーターはFunc戻り値の型です。他のすべてはパラメータタイプです。
異なる名前の類似したタイプがありますが、それらをインラインで宣言するための構文は同じです。この例はComparison<T>、です。これは、とほぼ同等Func<T, T, int>です。
Func<string, string, int> compare1 = (l,r) => 1;
Comparison<string> compare2 = (l, r) => 1;
Comparison<string> compare3 = compare1; // this one only works from C# 4.0 onwards
これらは、通常のメソッドであるかのように直接呼び出すことができます。
int x = add(23, 17); // x == 40
print(x); // outputs 40
helloWorld(x); // helloWorld has one int parameter declared: Action<int>
// even though it does not make any use of it.
「インライン関数」の意味に応じて、質問に対する答えは「はい」と「いいえ」です。C ++開発で使用されているような用語を使用している場合、答えはノーです。それはできません。ラムダ式でさえ関数呼び出しです。インラインラムダ式を定義してC#の関数宣言を置き換えることができるのは事実ですが、コンパイラーは無名関数を作成することになります。
これをテストするために使用した非常に単純なコードを次に示します(VS2015)。
static void Main(string[] args)
{
Func<int, int> incr = a => a + 1;
Console.WriteLine($"P1 = {incr(5)}");
}
コンパイラは何を生成しますか?生成された実際のILアセンブリを表示するILSpyと呼ばれる気の利いたツールを使用しました。見てください(私は多くのクラス設定のものを省略しました)
これがメイン機能です。
IL_001f: stloc.0
IL_0020: ldstr "P1 = {0}"
IL_0025: ldloc.0
IL_0026: ldc.i4.5
IL_0027: callvirt instance !1 class [mscorlib]System.Func`2<int32, int32>::Invoke(!0)
IL_002c: box [mscorlib]System.Int32
IL_0031: call string [mscorlib]System.String::Format(string, object)
IL_0036: call void [mscorlib]System.Console::WriteLine(string)
IL_003b: ret
それらの行IL_0026およびIL_0027を参照してください。これらの2つの命令は、数値5をロードし、関数を呼び出します。次に、IL_0031およびIL_0036をフォーマットして、結果を出力します。
そして、これが呼ばれる関数です:
.method assembly hidebysig
instance int32 '<Main>b__0_0' (
int32 a
) cil managed
{
// Method begins at RVA 0x20ac
// Code size 4 (0x4)
.maxstack 8
IL_0000: ldarg.1
IL_0001: ldc.i4.1
IL_0002: add
IL_0003: ret
} // end of method '<>c'::'<Main>b__0_0'
本当に短い関数ですが、関数です。
これは最適化するために努力する価値がありますか?いや。1秒間に何千回も呼び出す場合でも、パフォーマンスがそれほど重要な場合は、C / C ++で記述されたネイティブコードを呼び出して作業を行うことを検討する必要があります。
私の経験では、読みやすさと保守性は、ほとんどの場合、数マイクロ秒の速度向上を最適化するよりも重要です。関数を使用して、コードを読みやすくし、変数のスコープを制御し、パフォーマンスについて心配する必要はありません。
「時期尚早の最適化は、プログラミングにおけるすべての悪(または少なくともそのほとんど)の根源です。」-ドナルド・クヌース
「正しく実行されないプログラムは速く実行する必要はありません」-私
codeいただけますか。つまり、Func <string、string> PrefixTrimmer = x => x ?? ""; codeこれは初めてで、MSDNドキュメントをよく理解していません
x ?? ""はnull合体演算子です。 msdn.microsoft.com/en-us/library/ms173224.aspx
x => (something)、xはパラメータであり、(something)は戻り値です。