Circle
オブジェクトを作成できるライブラリを使用していて、円の半径と中心を指定してそれを定義できる状況を想像してみてください。ただし、何らかの理由で、必要なflavour
パラメータも必要です。ここで、自分のアプリで実際にCircle
を使用する必要があるとしましょう。ただし、アプリの目的で、毎回フレーバーを_Flavours.Cardboard
_に設定できます。
これを「解決」するために、別の名前空間に独自のCircle
クラスを作成します。これは、radius
およびcenter
のみをパラメーターとして受け取りますが、外部ライブラリの暗黙的なコンバーターを持っていますCircle
クラスは、Circle(this.radius, this.center, Flavours.Cardboard)
オブジェクトを作成するだけです。したがって、他のタイプのCircle
が必要なすべての場所で、自動変換を実行します。
そのようなクラスを作成するとどうなりますか?より良い解決策はありますか?私のアプリケーションが、この外部ライブラリーの上に構築されたAPIであり、他のプログラマーが使用することを意図していた場合、何か違いはありますか?
alwaysは悪くありませんが、暗黙の変換が最良のオプションであることは非常にまれです。
問題があります。
一般的に、より良い解決策があります。
個人的に、私は#2が最も簡単に実装でき、設計の負担が最も少ないと感じています。他の人は、状況や、これらのクラスで他に何をしようとしているのかを考えれば、大丈夫です。
暗黙の変換は最後の手段であり、私が作成しようとしているC++スタイルのファンクターがある場合にのみ、価値があるように思えます-暗黙的にデリゲート型に変換する戦略オブジェクト。
説明しているシナリオを考えると、これは部分的な関数の適用という観点から考えることができます。
コンストラクターは関数です(少なくとも理論的には、C#では、コンストラクターを呼び出す「ファクトリー関数」を作成できます)。
Func<double, Point, Flavour, Circle> MakeCircle = (r, p, f) => new Circle(r, p, f);
部分的な適用については、以下で十分です:
public static Func<T1, T2, R> Partial<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T3 t3)
=> (t1, t2) => func(t1, t2, t3);
これで、2つのパラメーターのみを必要とするコンストラクターを取得できます。
Func<double, Point, Circle> MakeCardboardCircle = Circle.Partial(Flavours.Cardboard)
これで、目的のパラメーターを持つファクトリー関数ができました。
Circle c = MakeCardboardCircle(1.0, new Point(0, 0)))
ところで、これは、より機能的な観点から見ると、上記のオプション2と明らかに同等です。