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

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

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

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

リフレクション

リフレクションとは、プログラムの実行過程でプログラム自身の構造を読み取り、編集する事が出来るプロセスのことを指します

Q&A

解決済

2回答

3265閲覧

C#ではこのような書き方は避けるべきなのか

aridai1221

総合スコア45

C#

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

リフレクション

リフレクションとは、プログラムの実行過程でプログラム自身の構造を読み取り、編集する事が出来るプロセスのことを指します

0グッド

0クリップ

投稿2016/05/21 13:47

編集2016/05/21 14:34

C#初心者です。

複数のクラスのインスタンスを生成する方法について考えていました。

最初に考えたコードをコード1に示します。
Class1, Class2, ... のように連続する名前のクラスを作りました。

そしてこれらのインスタンスを生成するコードも書きました。
Program::createInstanceがそれです。

C#

1// コード1 2 3using System; 4 5class Program 6{ 7 public static void Main() 8 { 9 Console.WriteLine(createInstance(1).Name); 10 Console.WriteLine(createInstance(2).Name); 11 } 12 13 // インスタンスを生成する (例外に対する処理は今回は省いてあります) 14 public static ClassBase createInstance(int num) 15 => Activator.CreateInstance(Type.GetType($"Class{num}")) as ClassBase; 16} 17 18abstract class ClassBase 19{ 20 public abstract string Name { get; } 21} 22 23class Class1 : ClassBase 24{ 25 public override string Name 26 => "クラス1"; 27} 28 29class Class2 : ClassBase 30{ 31 public override string Name 32 => "クラス2"; 33}

例外処理などは省きましたが、このような感じです。

さて、このように書いてしまいましたが、
静的な型指定をした場合に比べて
危険なコードになったと思います。

なので、静的な型指定をする方法に変えてみました。
それをコード2に示します。

C#

1// コード2 2 3using System; 4 5class Program 6{ 7 public static void Main() 8 { 9 Console.WriteLine(createInstance(1).Name); 10 Console.WriteLine(createInstance(2).Name); 11 } 12 13 public static ClassBase createInstance(int num) 14 { 15 switch (num) 16 { 17 case 1: 18 return new Class1(); 19 20 case 2: 21 return new Class2(); 22 23 default: 24 return null; 25 } 26 } 27} 28 29abstract class ClassBase 30{ 31 public abstract string Name { get; } 32} 33 34class Class1 : ClassBase 35{ 36 public override string Name 37 => "クラス1"; 38} 39 40class Class2 : ClassrBase 41{ 42 public override string Name 43 => "クラス2"; 44}

確かにコード2はコード1に比べて安全になったのかもしれませんが、
コードを書く量が増えました。

コード1中のProgram::createInstanceは
ClassBaseの派生クラスの数がどれだけ増えても1行、
例外を対処するコードを入れたとしても
それほど量は増えないでしょう。

それに対して、コード2中のProgram::createInstanceは
ClassBaseの派生クラスの数が増えれば増えるほど
コードが長くなります。

たとえば Class1 から Class718 までクラスがあるとすると
コード2の書き方でいけば
Program::createInstanceは2159行にもなることが予想されます。

いくら安全性のためとはいえ
これは大変だと思います。

そこで疑問に思いました。
皆さんなら
・コード1のやり方
・コード2のやり方
・それ以外のやり方
どのように書きますか。

追記
例を変えました。
あと、「必ずしもクラスにする必要は無いのではないか?」
という回答もやめてください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。

確かにコード2はコード1に比べて安全になったのかもしれませんが、

monsterIdに不正な値が渡された時どちらもエラー処理が必要です。そして、このケースならば前者もtry-catchすれば、安全性は大差ないような気がします。
C#処理系のバグまで視野に入れるとなんとなくリフレクションの信頼性は低いような気はしますが、それは気のせいかも。

ただ、それを除いてもリフレクションは遅いことと、使い方が妙に難しいのであまり積極的には使いたくないです。なので、派生クラスの数が精々一桁であれば私は後者を選ぶと思います。二桁越えるなら前者を選ぶかも。

投稿2016/05/21 14:34

Chironian

総合スコア23272

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

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

aridai1221

2016/05/21 14:45

回答ありがとうございます。 自分の中ではリフレクションは なんか怖いイメージが合ったので 使っていいのかどうか迷っていました。 やはり、数が多い場合は 使うのも手ですよね。
guest

0

派生クラスが700以上もあるとなると、やはりコード1方式がベースになるかと。
ただし、実在するクラス名であることをテストする Assert() を入れるか、せめて try catch で例外をハンドリングするくらいのことは必要ではないかと思います。

投稿2016/05/21 14:13

tkanda

総合スコア2425

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

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

aridai1221

2016/05/21 14:24

回答ありがとうございます。 昔、コード1のようなコードは めったに書くもんでないと教わったので 今回のようなときに使うかどうかを迷っていました。 あと、例外に対する処理はちゃんと入れておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問