最近、Enum
を使用すると言われました:
public enum TaskEndState { Error, Completed, Running }
互換性/シリアライゼーションの問題がある可能性があるため、const文字列を使用する方が良い場合があります。
public const string TASK_END_STATE = "END_STATE";
public const string TASK_END_STATE_ERROR = "TASK_END_STATE_ERROR";
public const string TASK_END_STATE_COMPLETE = "TASK_END_STATE_COMPLETE";
public const string TASK_END_STATE_RUNNING = "TASK_END_STATE_RUNNING";
それが発生する可能性のある実用的なユースケースを見つけることができますか、Enum
を避けるべきガイドラインはありますか?
編集:私の運用環境には複数のWFCサービス(同じ製品の異なるバージョン)があります。それ以降のバージョンにはTask end stateとして新しいプロパティが含まれる場合と含まれない場合があります(これは単なる例です)。特定のサービスの古いバージョンで新しいEnum
値を逆シリアル化しようとすると、機能しない可能性があります。
ここで重要なのは、Enum
をどの程度正確にシリアル化するかということではありません。あなたがそれを基礎となる整数値としてシリアル化すると仮定します。その場合、Enum
の途中に新しい値を追加すると、現在のコードには実際にバージョン管理の問題があります。
たとえば、現在のコードでは、Error
は0、Completed
は1、Running
は2です。コードを次のように変更したとします。
public enum TaskEndState { Error, Timeout, Completed, Running }
突然、Running
(古い2)として保存したものがCompleted
(新しい2)として読み取られますが、これは正しくありません。
これに対処する最良の方法は、各列挙型メンバーの数値を明示的に指定し、それらを変更しないことです。新しい値を最後に追加できますが、新しい整数値が必要です。たとえば、オリジナル:
public enum TaskEndState { Error = 0, Completed = 1, Running = 2 }
そして修正されたバージョン:
public enum TaskEndState { Error = 0, Timeout = 3, Completed = 1, Running = 2 }
この質問に対する正しい答えはありません。要するに、契約をどの程度明示的にしたいかということです。
一方では、このデータをTaskEndState
という名前のxsd:string
要素として単純に送信できます。ここで、コントラクトはメッセージ内の任意の文字列を取ります。メッセージで送信された文字列がコードの既知の値と一致することを確認するには、コードで検証を実行する必要があります。契約を変更せずに新しいコードを追加できます。これはそれほど明確ではない契約です。このタイプのコントラクトは変更がより柔軟ですが、一部の検証はコード内で発生する必要があるため、検証はスキーマレベルでのみ実行されなくなりました。
一方、xsd:string
要素には、定義された値のみを受け入れる制限(列挙)を定義できます。検証はスキーマレベルでのみ行われます。新しいコードを追加できますが、それによって契約が変更されます。これは明示的な契約です。このタイプのコントラクトは変更に柔軟性がありませんが、検証はスキーマレベルで1か所で実行されます。場合によっては、スキーマの検証が一元化された場所で実行され、メッセージの検証が実際のメッセージ処理から分離されるという一般的な合意があるため、これが望ましい場合があります。ただし、契約が変更されたため、発信者は追加の制限が何も壊していないことを再テストして検証する必要があります。
一般に、契約はできるだけ明示的にするのが好きなので、通常は列挙型を使用します。しかし、絶対的なものはありません。
あなたの場合、新しい文字列がそれほど頻繁に追加されない場合は、列挙型を使用します。 TaskEndStateデータが非常に揮発性が高い(絶えず変化する)場合は、汎用文字列を使用します。
制限を処理する方法をオンラインでいくつかの良い記事があります。以下はそのようなリンクの1つです。