C# で関数の引数をデフォルトにする唯一の方法はオーバーロードですか?
-
09-06-2019 - |
質問
デフォルトの関数引数を処理する唯一の方法は関数のオーバーロードによるものであるというのは本当ですか?
たとえば、PHP では次のことができます。
function foo($x, $y=0)
{
}
C#でそれを処理する最良の方法はこれでしょうか?
void foo(int x)
{
foo(x, 0);
}
void foo(int x, int y)
{
}
編集
C# サンプルを実際の C# にしました (Blair Conrad に感謝)
解決
はい、それが一番いいでしょう, ただし、 , 、他の人が指摘したように。デフォルトのパラメーター値がない理由に興味がある人は、@Giovanni Galbo の説明を参照してください。$
パラメータ名について
他のヒント
ちょっとした好奇心を満たすために:
から C# がデフォルトのパラメーターをサポートしないのはなぜですか?:
C++ などの言語では、メソッド宣言の一部としてデフォルト値を含めることができます。
void Process(従業員従業員、ブールボーナス = false)
このメソッドは次のいずれかを使用して呼び出すことができます。
a.プロセス(従業員、true);
または
a.プロセス(従業員);
2 番目のケースでは、パラメーターボーナスが false に設定されます。
C# にはこの機能がありません。
この機能がない理由の 1 つは、この機能の特定の実装に関連しています。C++ の世界では、ユーザーが次のように記述すると、
a.プロセス(従業員);
コンパイラが生成する
a.process(従業員、false);
つまり、コンパイラは、メソッド プロトタイプで指定されたデフォルト値を取得し、それをメソッド呼び出しに組み込みます。これは、ユーザーが 2 番目のパラメータとして「false」を書き込んだのと同じです。残念なことに、クラスのユーザーに再コンパイルを強制せずにデフォルト値を変更する方法はありません。
この点では、オーバーロード モデルの方がうまく機能します。フレームワークの作成者は 2 つの別々のメソッドを定義するだけで、単一パラメーターのメソッドは 2 パラメーターのメソッドを呼び出します。これにより、デフォルト値がフレームワークに保持され、必要に応じて変更できます。
コンパイラが C++ 定義のようなものを取得してオーバーロードを生成することは可能ですが、そのアプローチにはいくつかの問題があります。
1 つ目は、ユーザーが作成したコードとコンパイラーが生成するコードの間の相関関係がそれほど明白ではないということです。プログラマーにとっては困難になるため、私たちは通常、可能な限りマジックを制限しようとします。2 番目の問題は、XML ドキュメント コメントやインテリセンスなどに関係します。コンパイラには、オーバーロードされたメソッドの doc コメントを生成する方法について特別なルールが必要であり、インテリセンスには、オーバーロードされたメソッドを 1 つのメソッドに折りたたむ機能が必要です。
自分でオーバーロードを作成するのは少し便利ではありませんが、許容できる解決策だと考えています。
については、 C# FAQ からの抜粋:
そこにリストされている問題のほとんどは VB.Net で解決されています (特にインテリセンスと XML コメントの問題)。つまり、それらは本当に危険な問題です。 C# チームが問題を解決できるコードが利用可能です。
もう 1 つの理由は、クラスのユーザーに再コンパイルを強制することに関係していますが、これも少し危険です。もし、あんたが 変化 フレームワーククラスのデフォルト値とユーザーが設定する値 ない 再コンパイルする必要があるため、ユーザーに危険が及びます デフォルト値が変更されたことを知りませんでした。 コードには実行時まで現れない潜在的なバグがあります。言い換えれば、関数をオーバーロードするという代替案は、少なくとも同じくらい悪いということです。もちろん、これも機能の特定の実装を前提としていますが、それは FAQ で提案されている実装です。
したがって、残りの理由 (「魔法を制限しようとする」) と、オーバーロードを書くのが「少し便利ではない」という事実 (彼らも認めている) を比較検討する必要があります。個人的には、その機能を組み込み、それを使用するかどうかはプログラマに決定させるべきだと思います。
デフォルト引数は C++ の一部ですが、C# 3.5 の時点ではデフォルト引数はまだサポートされていないため、オーバーロードする必要があります。これらは VB.Net 1.0 以降で利用可能です。
はい。
あるいはカレー作り。
または、クラスに抽象化して、そこでデフォルト値を使用します。
いいえ、私の知る限り、C# はオーバーライドをサポートしていません。はい、それが同じ効果を達成するための推奨される方法です。
指摘したように、これは現在 C# では利用できませんが、Sam Ng がブログで説明しているように C# 4.0 には存在する予定です。
これでは仕事がうまくいきませんか?
void foo(int x):this(x, 0){}
void foo(int x, int y){
// code here
}