異なる引数型の組み合わせをとることができるC#メソッドを記述することが可能かどうか疑問に思っています。異なる引数型の組み合わせによるメソッド
たとえば、このメソッドは4つのオーバーロードされたメソッドを1つに結合します。
public static void MyMethod((JObject or File) jsonOne, (JObject or File) jsonTwo) {}
異なる引数型の組み合わせをとることができるC#メソッドを記述することが可能かどうか疑問に思っています。異なる引数型の組み合わせによるメソッド
たとえば、このメソッドは4つのオーバーロードされたメソッドを1つに結合します。
public static void MyMethod((JObject or File) jsonOne, (JObject or File) jsonTwo) {}
いいえ、特定のパラメータに対して2つの固定タイプのいずれかを受け入れることができる単一のメソッドオーバーロードを作成することはできません。
複数のオーバーロードを回避しながらも、最高の方法は新しいタイプを作成することです.2つの異なるタイプのいずれかを使用してインスタンスを作成し、というインスタンスを受け入れることができます。。
public class MyJSON
{
public MyJSON(JObject json)
{
FirstOption = json;
FirstOptionValid = true;
}
public MyJSON(File json)
{
SecondOption = json;
SecondOptionValid = true;
}
public JObject FirstOption { get; private set; }
public bool FirstOptionValid { get; private set; }
public File SecondOption { get; private set; }
public bool SecondOptionValid { get; private set; }
public static implicit operator MyJSON(File json)
{
return new MyJSON(json);
}
public static implicit operator MyJSON(JObject json)
{
return new MyJSON(json);
}
}
ユーザーが実際にも、明示的にすべての中間オブジェクトを構築するために必要とせず、MyMethod
にJObject
またはFile
オブジェクトを渡すことができるようにあなたもJObject
とFile
からMyJSON
に暗黙的な変換を作成することができます。実際に
、それがジェネリックを使用しての種類の任意の固定数のためにこれを一般化するために、実際には非常に簡単です:
public class Option<T1, T2>
{
public Option(T1 value)
{
FirstOption = value;
FirstOptionValid = true;
}
public Option(T2 value)
{
SecondOption = value;
SecondOptionValid = true;
}
public T1 FirstOption { get; private set; }
public bool FirstOptionValid { get; private set; }
public T2 SecondOption { get; private set; }
public bool SecondOptionValid { get; private set; }
public static implicit operator Option<T1, T2>(T2 value)
{
return new Option<T1, T2>(value);
}
public static implicit operator Option<T1, T2>(T1 value)
{
return new Option<T1, T2>(value);
}
}
現在のようにあなたの方法を書くことができます。
public static void MyMethod(Option<JObject, File> json1, Option<JObject, File> json2)
これはすでに述べたように、必要とされる各タイプごとに異なる署名を持つ多重オーバーロードを持つ方がはるかに意味があります。 – GJKH
@GJKHそれは状況によって異なります。複数のオーバーロードは2つのオプションを持つ1つのパラメータに対しては問題ありませんが、指定されたパラメータの数とパラメータの数の両方で指数関数的に変化しますが、これは線形に比例します。パラメータが少ない場合は、これがより簡単になります。 – Servy
これは、 'MyJSON'が' JObject'または 'File'からの作成であるかどうかを知る必要がないように、メソッドがこれらの2つの型から必要とするものを公開するように拡張できます。しかし、実際には、メソッドがそれらをどのように処理するかがまさに異なるかどうかにかかっています。 – juharr
二つの可能性が、汚れた解決策:
1(受理対象と型検査)
public static void MyMethod(object one, object two)
{
if(one is JObject) // handle
else if(one is File) // handle
else throw SomeException();
...
第PARAM
つのために同じオプションparamsは
public static void MyMethod(JObject jone = null, File fone = null,
JObject jtwo = null, File ftwo = null)
{
if(jone == null && fone == null)
throw SomeException();
else
// use set values and do stuff
...
はい、ドットは...あなたがすべてのパラメータでそれを行う必要があることを示すはずです。私は2番目の部分を省略しました。 –
は、わかりやすさのために私の答えを更新しました –
*これらのソリューションの* *はすべて静的型安全性を失い、最初はすべての型安全性を完全に失い、メソッドを極端に使いにくくし、オブジェクトの各ペアのうちの1つだけが値を持つべきであることを意味します( 'null'を有効にすることは決して正しい値ではありません。正しい仮定ではないかもしれません)。また、可能な型の数各パラメータの型オプションが同じでない場合は、呼び出し元にとってさらに混乱します。 – Servy
下記参照コード:
interface IDo {
void DoSomething();
}
class MyFile : File, IDo {
void DoSomething() {
// blah blah
}
}
class MyJObject : JObject, IDo {
void DoSomething() {
// blah blah
}
}
public static void MyMethod<T1, T2>(T1 one, T2 two)
where T1 : IDo
where T2 : IDo
{
one.DoSomething();
two.DoSomething();
}
ファイル及び/又はjオブジェクト場合が封止され、その後、代わりに継承の封じ込めを使用:
class MyFile : IDo {
File file;
void DoSomething() {
// blah blah
}
}
class MyJObject : IDo {
JObject jObject;
void DoSomething() {
// blah blah
}
}
どのような利点がありますか?異なる署名を持つ複数のオーバーロードを提供する。 –
内部的には、各パラメータのタイプを把握して適切に処理するためのコードを記述する必要があります。その時点で別のメソッドのオーバーロードが発生する可能性があります。 –
'JObject'クラスと' File'クラスはかなり異なるメンバを持ち、共通のインタフェースを実装していません。だから、この "結合された"メソッドは 'if(jsonOne is File){.....}のようなスパゲッティコードでいっぱいになりますelse if(isonOneはJObjectです){...}' –