質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

5101閲覧

引数のないオーバーロードを実装するためにはどうしたらよいでしょうか?

jinskyline

総合スコア42

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/01/31 15:21

「AからB(C)を生成する」と実装したいのですが、引数がないオーバーロードになってしまいC#言語の規約上エラーになってしまいます。
このような場合、どのように工夫してコードにしたらよいのか教えてください。
0. クラスAはWebサービスの引数として受け取ります。
0. クラスAはインターフェイスとしてプロパティが確定しています。
0. クラスB,Cは内部で使用するクラスです。
0. クラスB,Cはまだ変更が可能な状態です。
0. クラスAからB,Cを生成する関数を定義したいです。

C#

1namespace T 2{ 3 class A 4 { 5 public int aa { get; set; } 6 public string bb { get; set; } 7 public string cc { get; set; } 8 } 9 10 class B 11 { 12 public int aa { get; set; } 13 public string bb { get; set; } 14 public bool xx { get; set; } 15 } 16 17 class C 18 { 19 public int aa { get; set; } 20 public int yy { get; set; } 21 } 22 23 static class Ax 24 { 25 public static B Generate(this A a) 26 { 27 return new B { aa = a.aa, bb = a.bb, xx = false }; 28 } 29 public static C Generate(this A a) 30 { 31 return new C { aa = a.aa, yy = Convert.ToInt32(a.bb) }; 32 } 33 } 34 class Program 35 { 36 static void Main(string[] args) 37 { 38 var a = new A { aa = 1, bb = "2", cc = "A" }; 39 new Program().Service(a); 40 } 41 42 public void Service(A a) 43 { 44 B b = a.Generate(); 45 C c = a.Generate(); 46 } 47 } 48}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

私もGenerateBとGenerateCに分ける方法に賛成です。
ただし、この先内部クラスがD,E,Fと増えていく可能性がある場合、
ジェネリックメソッドを使用することも視野に入れると良いかもしれません。

また、それとは別にクラスBとCの値の初期化をAxのGenerateに記述してしまうと、
後で変更が必要になった際に変更箇所がわからなくなる可能性があるかと思います。
クラスB、クラスCにはそれぞれ、Aを引数に取る初期化メソッドを用意した方がよいでしょう。
メソッド名を分ける場合はAを引数に取るコンストラクタを追加すればよいと思います。
ジェネリックにする場合はコンストラクタに引数を設定することができない(これはジェネリックの致命的な弱点だと思います;)ので、基底インターフェースに初期化メソッドを定義し、それを実装するのがよいでしょう。
(ジェネリックメソッドGenerateによって初期化メソッドが呼ばれることは保障され、インターフェースIBaseによって内部クラスが初期化メソッドを実装することが保障されます。)

namespace T
{
class A
{
public int aa { get; set; }
public string bb { get; set; }
public string cc { get; set; }
}

// 内部クラスの基底となるインターフェース interface IBase { void Initialize( A a ); } // 基底インターフェースを実装 class B : IBase { public int aa { get; set; } public string bb { get; set; } public bool xx { get; set; } // 初期化はクラス内に記述する。 public void Initialize( A a ) { aa = a.aa; bb = a.bb; xx = false; } } class C : IBase { public int aa { get; set; } public int yy { get; set; } public void Initialize( A a ) { aa = a.aa; yy = Convert.ToInt32( a.bb ); } } // 内部クラスを増やす際はクラスを増やすだけでよく、 // Generateへの変更は必要ない。 class D : IBase { public int aa { get; set; } public double zz { get; set; } public void Initialize( A a ) { aa = a.aa; zz = Convert.ToDouble( a.bb ); } } static class Ax { // IBaseを実装したクラスをジェネリック引数として渡すと、 // Aを元にそのクラスのインスタンスが生成される。 public static CLASSTYPE Generate<CLASSTYPE>( this A a ) where CLASSTYPE : IBase, new() { var newObject = new CLASSTYPE(); newObject.Initialize( a ); return newObject; } } class Program { static void Main( string[] args ) { var a = new A { aa = 1, bb = "2", cc = "A" }; new Program().Service( a ); } public void Service( A a ) { B b = a.Generate<B>(); C c = a.Generate<C>(); D d = a.Generate<D>(); } }

}

投稿2016/02/05 21:39

hiramaru

総合スコア48

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jinskyline

2016/02/09 03:44

hiramaruさま 私のつたない質問の意図を拾って頂き、ありがとうございます。 実はAはサービスに起因する外部仕様で決まっているクラスで、B~はテーブル定義に起因するバリューオブジェクト(ベース)になります。 「サービスモデルAから各バリューオブジェクト(B~)を展開する」をコード化しようとしたところで、思考が迷宮入りしてしまいました。 ご教授頂いたこの方法が、今の自分の思考にとてもフィットします。 ありがとうございました。
guest

0

こんにちは。

普通は下記のようにすると思います。

C#

1B b = a.GenerateB(); 2C c = a.GenerateC();

このようにできるようGenerateを書かない理由はなんでしょうか?
対策はその理由により変わります。

投稿2016/01/31 15:35

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jinskyline

2016/02/02 00:01

Chironianさま 回答ありがとうございます。 仰るとおりメソッド名に型名を追加すればオーバーロードにならないですね。 よくよく考えてみればサンプルで使用している ConvertもToXXXとなっていますね。 ご質問頂いた「理由」ですが、LINQのように型推論にしたかったのか、それともジェネリックのように型とメソッドを分離したかったのか、そんな「ふわっとした制約」に落ち込んでいたのかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問