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

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

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

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

列挙型

データ型の一種で、要素・メンバなど名前のある値や、型の列挙子によって構成されます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

3053閲覧

【C#】静的クラス内アルゴリズムの共通化・列挙型間の関連付け等

syogakusya

総合スコア67

C#

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

列挙型

データ型の一種で、要素・メンバなど名前のある値や、型の列挙子によって構成されます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

1クリップ

投稿2016/08/28 14:34

編集2016/08/28 14:41

###前提・実現したいこと
以下のソースが前提となります。
プロジェクトはProject1、Project2、Project3...とあり、
各プロジェクトにMessageProviderクラス及びMessageKind列挙型を実装します。
また、各プロジェクトからLowLevelAssembly名前空間を参照します。

C#

1namespace Project1 2{ 3 static class MessageProvider 4 { 5 public const int FirstErrorIndex = 20001; 6 public const int FirstInfoIndex = 10001; 7 8 public static LowLevelAssembly.MessageData GetMessageData(MessageKind messageKind) 9 { 10 return new LowLevelAssembly.MessageData 11 { 12 Id = getId(messageKind), 13 Message = getMessage(messageKind), 14 MessageLevel = getMessageLevel(messageKind) 15 }; 16 } 17 18 private static string getMessage(MessageKind messageKind) 19 { 20 switch (messageKind) 21 { 22 case MessageKind.TaskDone: 23 return "all tasks are done"; 24 case MessageKind.CommandLineArgumentsError: 25 return "need some command-line arguments"; 26 case MessageKind.SpecialError: 27 return "failed to backup log files"; 28 default: 29 throw new ArgumentException("undefined"); 30 } 31 } 32 33 private static LowLevelAssembly.MessageLevel getMessageLevel(MessageKind messageKind) 34 { 35 var id = getId(messageKind); 36 if (id < FirstInfoIndex) 37 throw new ArgumentException("implimentation error"); 38 return id < FirstErrorIndex ? 39 LowLevelAssembly.MessageLevel.Info : 40 LowLevelAssembly.MessageLevel.Error; 41 } 42 43 private static int getId(MessageKind messageKind) 44 { 45 return (int)messageKind; 46 } 47 } 48 49 enum MessageKind 50 { 51 TaskDone = MessageProvider.FirstInfoIndex, 52 CommandLineArgumentsError = MessageProvider.FirstErrorIndex, 53 SpecialError 54 } 55} 56 57namespace LowLevelAssembly 58{ 59 public class MessageData 60 { 61 public string Message { get; set; } 62 public MessageLevel MessageLevel { get; set; } 63 public int Id { get; set; } 64 } 65 66 public enum MessageLevel 67 { 68 Info, 69 Error 70 } 71}

MessageProviderクラスに実装されているメソッドのうち、何らかの良い方法で
以下のメソッドを共通化することが今回実現したいことです。

  • GetMessageData
  • getId
  • getMessageLevel

##課題

継承を利用すれば、getMessageを抽象メソッドとして宣言し、FirstErrorIndex・LastErrorIndexは
抽象プロパティとして宣言することで解決に向かいそうですが、静的クラスのままでは継承できません。
そして、MessageProviderクラスは論理的に静的クラスであるべきだと現状では考えています。
また、MessageKindについて、列挙型は継承もインターフェースの実装も行うことができないため、
メソッドの引数には列挙型の基本クラスであるEnum抽象クラスを指定しなければなりません。
つまり、getId(DayOfWeek.Friday)のようなコードをコンパイルエラーとすることができません。

以上のような考察のもと、よりよいプログラミングを学びたいと思い、質問させて頂きました。
ご回答をお待ちしております。よろしくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

参考になるかわかりませんが、3点ほど書いてみます。

  1. constはコンパイル時に値が決まるので、毎回全プロジェクトビルドする場合は良いですが、

他プロジェクトからこの値を参照している場合にはこの定数を変えた場合には参照しているプロジェクトもコンパイルしなおす必要があります。回避するためにstatic readonlyにするという手があります。
ただ、列挙体も同じなのでconstだけ気にしてもだめですが。

  1. C#のメソッドは大文字始まりです。

  2. 静的クラスの継承については確かにできませんが、

Singletonでなんとかする手はあります。(以下のコード)

C#

1static class MessageProvider { 2 3 public const int FirstErrorIndex = 20001; 4 public const int FirstInfoIndex = 10001; 5 6 // このstaticクラス(MessageProvider)は、このインスタンスのラッパーになる感じです。 7 private static MessageProviderConcrete instance = new MessageProviderConcrete(); 8 9 public static LowLevelAssembly.MessageData GetMessageData(MessageKind messageKind) { 10 return instance.GetMessageData(messageKind); 11 } 12 13 private static string GetMessage(MessageKind messageKind) { 14 return instance.GetMessage(messageKind); 15 } 16 17 private static LowLevelAssembly.MessageLevel GetMessageLevel(MessageKind messageKind) { 18 return instance.GetMessageLevel(messageKind); 19 } 20 21 private static int GetId(MessageKind messageKind) { 22 return instance.GetId(messageKind); 23 } 24 25 // staticでないので、このクラスは継承などできる。 26 // MessageKindの位置によってはそれに影響されて結局継承できない可能性も。 27 public class MessageProviderConcrete { 28 internal MessageProviderConcrete() { 29 } 30 31 public LowLevelAssembly.MessageData GetMessageData(MessageKind messageKind) { 32 return new LowLevelAssembly.MessageData { 33 Id = GetId(messageKind), 34 Message = GetMessage(messageKind), 35 MessageLevel = GetMessageLevel(messageKind) 36 }; 37 } 38 // 以下の実装は省略。元と同じ。 39 protected internal string GetMessage(MessageKind messageKind) { 40 throw new NotImplementedException(""); 41 } 42 protected internal LowLevelAssembly.MessageLevel GetMessageLevel(MessageKind messageKind) { 43 throw new NotImplementedException(""); 44 } 45 protected internal int GetId(MessageKind messageKind) { 46 throw new NotImplementedException(""); 47 } 48 } 49 50 enum MessageKind { 51 TaskDone = MessageProvider.FirstInfoIndex, 52 CommandLineArgumentsError = MessageProvider.FirstErrorIndex, 53 SpecialError 54 } 55}

投稿2016/08/28 15:13

flied_onion

総合スコア2604

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問