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

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

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

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

Q&A

解決済

4回答

594閲覧

C# リテラルのResourceFile化について

siksmtt

総合スコア20

C#

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

0グッド

0クリップ

投稿2020/01/10 05:56

背景

C# + WPFでアプリケーションを作っています。
MessageBox.Show()で表示するメッセージや、ComboBoxのItemSourceで使われるアイテムを今はpublic static readonlyで定義しています。

ただ上記以外にもResourceFileに定義する方法をあることも知り、色々調べてみたのですが、
リテラルをResourceFileに定義する必要性に疑問を抱き質問しました。

詳細

例えば以下のコードで作られたアプリケーションがあるとします。

Xaml

1<Window ...Title="SubWindow" Height="250" Width="400"> 2 <StackPanel Margin="50"> 3 <ComboBox ItemsSource="{Binding ComboBoxItemSource}" SelectedIndex="{Binding ComboBoxSelectedIndex}" SelectionChanged="ComboBox_SelectionChanged"/> 4 <Label Content="{Binding LabelContext}" HorizontalAlignment="Center" VerticalAlignment="Center"/> 5 </StackPanel> 6</Window>

C#

1 public partial class SubWindow : Window 2 { 3 private ViewModelSubWindow mViewModel = new ViewModelSubWindow(); 4 5 public SubWindow() 6 { 7 InitializeComponent(); 8 this.DataContext = mViewModel; 9 } 10 11 private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 12 { 13 mViewModel.LabelContext = DefineWeek.getWeekName(mViewModel.ComboBoxSelectedIndex); 14 } 15 } 16 17 public class ViewModelSubWindow : DataBindingBase //DataBindingBaseは省略 18 { 19 public ViewModelSubWindow() 20 { 21 _comboBoxItemSource = DefineWeek.WeekList.Keys.Select(x => x.ToString()).ToList(); 22 } 23 24 private List<string> _comboBoxItemSource = new List<string>(); 25 public List<string> ComboBoxItemSource 26 { 27 get 28 { 29 return _comboBoxItemSource; 30 } 31 set 32 { 33 _comboBoxItemSource = value; 34 NotifyPropertyChanged(nameof(ComboBoxItemSource)); 35 } 36 } 37 38 private int _comboBoxSelectedIndex = 0; 39 public int ComboBoxSelectedIndex 40 { 41 get 42 { 43 return _comboBoxSelectedIndex; 44 } 45 set 46 { 47 _comboBoxSelectedIndex = value; 48 NotifyPropertyChanged(nameof(ComboBoxSelectedIndex)); 49 } 50 } 51 52 private string _labelContext = ""; 53 public string LabelContext 54 { 55 get 56 { 57 return _labelContext; 58 } 59 set 60 { 61 _labelContext = value; 62 NotifyPropertyChanged(nameof(LabelContext)); 63 } 64 } 65 } 66 67 public class DefineWeek 68 { 69 public static readonly string Sunday = "日曜"; 70 public static readonly string Monday = "月曜"; 71 public static readonly string Tuesday = "火曜"; 72 public static readonly string Wednesday = "水曜"; 73 public static readonly string Thursday = "木曜"; 74 public static readonly string Friday = "金曜"; 75 public static readonly string Saturday = "土曜"; 76 77 public static Dictionary<int, string> WeekList { get; private set; } = new Dictionary<int, string>() 78 { 79 { 0, Sunday }, 80 { 1, Monday }, 81 { 2, Tuesday }, 82 { 3, Wednesday }, 83 { 4, Thursday }, 84 { 5, Friday }, 85 { 6, Saturday } 86 }; 87 88 public static string getWeekName(int pWeekId) 89 { 90 if (WeekList.Count < 1) 91 { 92 return ""; 93 } 94 95 return WeekList.FirstOrDefault(item => item.Key == pWeekId).Value; 96 } 97 }

このアプリケーションは以下のような仕様です。
・仕様1:ユーザがComboBoxおよびLabelの表示内容を追加・削除・編集することはできない
・仕様2:対応言語は日本語のみであり今後変更・拡張される予定はない
・仕様3:DefineWeekクラスを将来的にDLL化する可能性はある
・仕様4:各クラスと各ファイルが1対1にしなければならない
→ 例)aaa.csファイルにはaaaクラスしか定義できない。

上記のような場合、DefineWeekクラスの定数をResourceFileにて定義することもできると思いますが、
以下の理由からResourceFileにするのは不適切かなと考えました。

  • 理由1:DefineWeek.WeekListのように数値とリテラルをペアで扱いたい上、DefineWeek.getWeekName()のように数値に基づいてリテラルを取得することがコーディング面から容易である

→ ResourceFileにするとまずDefineWeek.WeekListのようなDictionalyを作る必要があり、それは冗長だと思っている
→ Dictionalyを作らない場合switchで都度判別することになり、それも冗長だと思っている

  • 理由2:DefineWeekpublic static readonly string Holiday = "祝日";などが増えたり、既存の曜日が必要なくなった場合を考慮し保守がしやすい
  • 理由3:DefineWeekクラスがDLLになり修正が行われた際、参照側のプログラムをリビルドする必要がなくなると考えている(バージョニング問題の対策)

ですがResourceFileについて調べると、リテラルもResourceFileで定義するのが当たり前なのかと思われるほど、
ResourceFileで定義するサンプルを見かけます。
アイコンなどのイメージ画像やテキストファイルであれば納得もできますが...。

質問

1、上記のようにリテラルをResourceFileに定義しないのは間違いなのでしょうか?(設計自体問題があるというご指摘でも構いません)
2、リテラルをResourceFileに定義しない場合のデメリット、定義する場合のメリットを知りたいです。

ご助言いただけますと幸いです。よろしくお願いします。

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

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

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

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

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

guest

回答4

0

そもそも「リテラルをResourceFileに定義する必要性」はどこから来た概念でしょうか?
「多言語化に対応するなら ResourceFile を用いましょう」なら解りますが、「リテラルをResourceFileに定義する必要性」など聞いたことがありません。
Visual Studio で開発するうえでリソースっぽいものの登録の仕方は有名どころだけで10を超えます。
リテラルが散在しているのは問題ですが、リテラルと ResourceFile を結び付ける必然性はありません。

投稿2020/01/10 09:12

hihijiji

総合スコア4150

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

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

siksmtt

2020/01/11 09:27

hihijiji様 ご回答ありがとうございます。 自分は組織に属しており、C++を専門とした先輩プログラマーがいるのですが、その人の意見としてはリテラルはResourceFileに定義するべきということなのです。 ただネットで調べた上で「本当にそうする必要があるのか?」を考えたところ「場合によっては必ずしもそうしなくても良い」と思ったので、質問させていただきました。 リテラルが散在している点につては自分も別問題だと思うので、その点には気を付けようと思います!
hihijiji

2020/01/11 10:04

いざとなったらResourceFileからT4テンプレートを使ってクラスを生成することも出来なくはないです。 T4テンプレートは使っている人が少なくてマイナーですが、使いこなすと便利ですよ。
siksmtt

2020/01/14 00:55

hihijiji様 補足ありがとうございます。 T4テンプレートとな、こんな便利な機能があるんですね...! 参考にさせていただきます!
guest

0

  1. 間違いとは思いません。ただ、質問者さんの属する開発チームのルールとか質問者さんの独自の事情とかがあって問題はあるかもしれないとは思いますが。

  2. メリット・デメリットも質問者さんの事情によるものが大きく、その事情を知らない他人がアドバイスできるものではなさそうと思います。

個人的には国際化不要なら settings ファイルを使うとか、場合によってはハードコーディングしても差し障りないケースもあると思います。でも、組織のルールとかがあれば個人の意見はおいといてそれに従うということになるかと。

という訳で、組織内で話し合ってルールを決めてはいかがでしょう?

組織には属してなくて、保守まで含めて個人開発ということであれば、質問を拝見すると個人的な強いこだわりのようなものがありそうなので、ご自分が納得できるようにすれば良いと思ってしまいます。

投稿2020/01/10 22:46

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

siksmtt

2020/01/11 09:30

SurferOnWww様 ご回答ありがとうございます。 hihijiji様の回答に書いたように、属している組織の先輩の意見に疑問をもったので質問させていただきました。 プログラムのメモリや速度面で大幅な問題がなければ、リソースファイル以外の方法も検討しようと思ったのですが、 (国際化対応が不要な点を除けば)大きな問題はないように思えるので、頂いたご回答を基に開発陣で決めようと思います!
guest

0

ベストアンサー

アプリケーションのビジネスが、複数言語や複数地域を対象にしている場合、プログラミングのパターンとして、リソースファイルを常に使います。言語毎のリソースファイルのスイッチは、OS からサポートされているので、パターン化しています。リテラルと言うか、コンスタントなデータはハードコードしますが、なるべく一箇所にまとめます。イメージデータなども、場合によっては、言語や地域によって変える必要がある時もあり、リソースファイルのの対象になることもあります。
その他メリットとして、リソースファイルはプログラムコードでは無いので、プログラマーでない人が直接レビューして変更をすることができます。例えば、ドキュメント担当者が、リソースファイルをチェックします。
アプリケーションの対象が、日本国内だけであれば、問題が発生することはないと思いますが、データリソースとプログラムコードを分離する点では、すっきりとしたパターンになると思います。ただ、りそーふファイルを導入して、余計な作業が増えるのであれば、無駄なデザインとも言えます。
リソースファイルは、xml、json などのフォーマットで、コンバーターを使って、コードを生成し、プログラムから簡単にアクセスできるようになってます。

投稿2020/01/10 07:36

編集2020/01/10 15:16
mmaeda

総合スコア269

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

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

siksmtt

2020/01/10 08:07

mmaeda様 回答ありがとうございます。 リソースファイルのメリットが分かりやすく理解が深まりました! 確かにプログラマーではない人がリソースファイルをチェックできる点や、 コンバーターを用いて他のフォーマットでの管理ができる点は非常に良いですね。 1点だけ質問させてください。 「コンスタントなデータはハードコードしますが、なるべく一箇所にまとめます。」についてですが、 例えばもし今回のように週の定義に加えて16進数カラーコードの定義など、 全く関係性がない定義が追加された場合も1か所にまとめるのでしょうか? (「アプリケーションの対象が ... 無駄なデザインとも言えます。」についてはリソースファイルを使わない場合の話ととらえていますので、認識相違があればご指摘ください。)
mmaeda

2020/01/10 15:22

ユーザーに表示される文字データと、それ以外で使用するデータは分離します。文字のデータファイルとそれに付加するカラーコードがあれば、多言語対応にするためには分けます。 カラーコードはプログラムの一部で、文字データはリソースです。文字でも、内部でしか使用しない場合は、コンスタントして取り扱い、ハードーコードします。
siksmtt

2020/01/11 09:23

mmaeda様 追加のご回答ありがとうございます。 なるほど、リソースファイルの活用方法がとても理解できました!たしかにプログラム内部でしか使用しない文字をリソースファイルにする必要はないですもんね...。重ね重ね、ありがとうございました!
guest

0

操作ミスで回答がダブって二つできてしまいました。すみません。こちらを削除させていただきます。

投稿2020/01/10 22:34

編集2020/01/10 23:03
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問