10117


enumをシリアライズする必要のあるプログラムを設計しています。

enumの値を変更するとシリアライズしたデータが矛盾するということは理解していますが、運用開始後も仕様変更によるenum値の変更が回避できません。  
enumは変更に対して柔軟ではないように思えますが、よいenumの使い方はあるでしょうか？  
あるいは、enum以外の方法（文字列を使うなど）がよいのでしょうか？

具体的には下記のように`TokenType`を定義しています。  
`TokenType`は`tokenType <= TokenType.SystemC`のような条件の使い方もします。  
また、`Token`は`Dictionary`のキーとして使用します

[code]

    [Serializable]
    public enum TokenType : ushort
    {
        Empty = 0,
        SystemA = 1,
        SystemB = 2,
        SystemC = 3,
        PluginX = 256,
        // 今後 SystemD や PluginY が追加される可能性がある
    }
    
    [Serializable]
    public struct Token
    {
        public TokenType Type;
        public ushort ID;
    }
    
[/code]


CC BY-SA 3.0
2015-05-12T12:41:54.820
10078
2015-05-13T09:30:04.583
2015-05-12T13:42:16.100
8000
8870
question
c# .net
値の追加変更に柔軟なenumの使い方


`XmlSerializer`や`XamlXmlWriter`は列挙型を文字列でシリアライズしたかと思います。  
仕様確定前はこれらの方式でいいのでは。


CC BY-SA 3.0
2015-05-12T13:01:20.723
10079
2015-05-12T13:01:20.723
5750
10078
answer


enumを変更しても対応する値は変更しないという条件であれば以下でどうでしょうか？  
(#SystemBが無効になって、SystemD,PluginY,PluginZを追加の場合です)

[code]

    [Serializable]
    public enum TokenType : ushort
    {
        Empty = 0,
        SystemA,
        [ObsoleteAttribute(), EditorBrowsable(EditorBrowsableState.Advanced)]
        SystemB, //使わなくなっても消さない
        SystemC,
        PluginX,
        //以前の並びは変更しないで
    
        //そのまま追加の順番でEnumに値を自動振付する
        SystemD,
        PluginY,
        PluginZ,
    }
    
    internal enum SystemXXX : ushort
    {
        A = TokenType.SystemA,
        //B = TokenType.SystemB, //使わなくなったのでこちらでは消すのは可能(場合による)
        C = TokenType.SystemC,
        D = TokenType.SystemD,
    
    }
    
    internal enum PluginXXX : ushort
    {
        X = TokenType.PluginX,
        Y = TokenType.PluginY,
        Z = TokenType.PluginZ,
    }
    
    #pragma warning disable 612
    internal enum Obsolete
    {
        B = TokenType.SystemB
    }
    #pragma warning restore 612
    
    /// <summary>拡張メソッド</summary>
    static class Extension
    {
        /// <summary>逆シリアル化で無効な値が入ってきたかチェックするのに使う</summary>
        public static bool IsValid(this TokenType value)
        {
            return IsObsolete(value) || !Enum.IsDefined(typeof(TokenType), value);
        }
    
        /// <summary>削除済みか</summary>
        public static bool IsObsolete(this TokenType value)
        {
            return Enum.IsDefined(typeof(Obsolete), (Obsolete)value);
        }
    
        public static bool IsSystem(this TokenType value)
        {
            return Enum.IsDefined(typeof(SystemXXX), (SystemXXX)value);
        }
        public static bool IsPlugin(this TokenType value)
        {
            return Enum.IsDefined(typeof(PluginXXX), (PluginXXX)value);
        }
    
        public static int CompareTo(this TokenType value, SystemXXX s)
        {
            return value.CompareTo((TokenType)s);
        }
        public static int CompareTo(this TokenType value, PluginXXX p)
        {
            return value.CompareTo((TokenType)p);
        }
    }
    
[/code]


CC BY-SA 3.0
2015-05-13T09:30:04.583
10117
2015-05-13T09:30:04.583
4926
10078
answer