あいまいさであろうと、提供される追加機能であろうと、掘り下げたいと思います。
public class Foo
{
public int Bar(){
//code
}
public string Bar(int a){
//code
}
}
これについて経験がある人は、異なるパラメータで戻り値の型をオーバーロードするのは悪い習慣でしょうか?
しかし、オーバーロードが戻り値の型に基づいて行われた場合、なぜこれが機能しないのか。
public class Foo
{
public int Bar(int a){
//code
}
public string Bar(int a){
//code
}
}
Obj.Bar()を呼び出すと、1番目または2番目に呼び出す関数を決定できないためです。 、最初のコードスニペットの実行を許可する理由がわかれば、エラーで終了するはずです。
C#仕様(セクション10.6)には、オーバーロードされたメンバーが戻り値の型と http://msdn.Microsoft.com/en-us/library/ms229029.aspx によってのみ異ならないことが記載されています
異なる戻り値の型をサポートするためだけにパラメータを作成することに関するあなたの質問によると?私は個人的にそれが問題の恐ろしい解決策だと信じています。コードのメンテナンスが困難になり、未使用のパラメーターは明確なコード臭です。その場合、メソッドは本当にオーバーロードする必要がありますか?それともそのクラスに属しますか?ある戻り値の型から別の戻り値の型に変換するために何か他のものを作成する必要がありますか?もっと慣用的な解決策を導き出すためにあなたが尋ねるべきすべてのもの。
これは論理的に不可能です。次の呼び出しを検討してください。
object o = Bar(42);
あるいは
var o = Bar(42);
コンパイラはどのメソッドを呼び出すべきかをどのようにして知るのでしょうか?
編集:あなたが実際に求めていることを理解したので、意味のないパラメータによるオーバーロードは悪い習慣であり、読みやすさを低下させると思うので、メソッド名で区別することがはるかに望ましいです:
string BarToStr()
{
}
int BarToInt()
{
}
他の人はすでに状況を説明しました。これを追加したいだけです。ジェネリック型パラメーターを使用することで、思い描いていることを実行できます。
public T Bar<T>(int a) {
// code
}
そして、次のように呼び出します:
int i = Bar<int>(42);
string s = Bar<string>(42);
問題は、ジェネリック型で何か意味のあることをするのが難しいことが多いことです。算術演算を適用することはできません。 一般的な型の制約 が役立つ場合があります。
戻り値の型だけを変えて関数をオーバーロードすることはできません。次の方法でのみ関数をオーバーロードできます
どの関数が実際に呼び出されるかを知ることはできません(可能な場合)。
私が追加したいもう1つのことは、関数のオーバーロードです同じ名前で異なるシグネチャを持つ関数を提供することですが、メソッドは、メソッドの署名の一部とは見なされません。
したがって、これはメソッドのオーバーロードが戻り値の型によってのみ実行できない理由を理解する別の方法です。
これについての経験がある人は、異なるパラメータで戻り値の型をオーバーロードするのは悪い習慣です。
私はそれを意味しています-「異なる戻り値の型を容易にするために異なるパラメータの組み合わせを使用するのは悪い習慣ですか?」-それが本当に問題であれば、他の誰かが数か月後にこのコードに遭遇することを想像してください-事実上「ダミー戻り値の型を決定するパラメーター...
編集-ChrisLavaが指摘するように、「これを回避する方法は、各関数に対して(オーバーロードの代わりに)より良い名前を付けることです。アプリケーション内で明確な意味を持つ名前。Barがintと文字列を返す理由はありません。 intでToString()を呼び出すだけです」
一方、C#は戻り値の型に基づくメソッド解決をサポートしていません。これは、それを可能にするCLRの機能を公開しないという、言語設計者による意識的な決定でした。彼らができなかった技術的な理由はありません。戻り値はメソッド選択に使用されないため、C#メソッドシグネチャには含まれません。
同じ名前、同じ数、同じ種類のパラメーターでメソッドを作成することはできません。
詳細については、これを参照してください link 。
コードはコンパイラエラーになります。同じパラメータと異なる戻り値型を持つ同じ名前のメソッドを持つことはできません、呼び出し元は呼び出すメソッドを知りません(呼び出すメソッドのメモリ内の場所を解決できないため、コンパイラはなぜ許可しない)。別の方法は、オブジェクトを返し、呼び出し元が知っていることに基づいてキャストすることです。それでも、それは悪いデザインのようです。
これは動作します(コンパイルを意味します)が、それでもデザインが悪い。
public class Foo
{
public object Bar(int a)
{
return a;
}
}
これを確認してください。同じ署名と異なる戻り値型を持つメソッドを使用することはできません。この質問には「推奨」が記載されています。