2017-03-13 2 views
1

int値を列挙型にキャストしているときに廃止された値をスキップする方法はありますか?私は以下の作業例を持っています:廃止された列挙を解析する

using System; 

public class Program 
{ 
    public static void Main() 
    { 
     int valueInt = 1; 
     var en = (TestObsolete)valueInt; 
     Console.WriteLine(en); 
    } 
} 

enum TestObsolete 
{ 
    Undefined, 
    [Obsolete] 
    ValueA = 1, 
    ValueB=1, 
} 

私はValueAを取得していますが、ValueBを取得することを期待しています。特に、私は、次のシグネチャを持つ一般的な方法に興味がある:

public static T ParseEnumWithoutObsolete<T>(int val) where T: struct { 

が、私はそのような何かをしようとした:

T @enum; 
var enumValues = Enum.GetValues(typeof(T)).Cast<T>(); 
var obsoleteValues = enumValues.Where(a => typeof(T).GetField(a.ToString()).CustomAttributes.Any(t => t is ObsoleteAttribute)); 
var activeValues = enumValues.Except(obsoleteValues); 

が、次の段階で立ち往生。

答えて

5

私はValueAを取得していますが、ValueBを取得する予定です。

あなたはValueAとしてParseとは何の関係もあり、ToStringで行うためにすべてを持っていないことをあなたはを見ているという事実1.整数で表される値を取得しています。

実際には、enum型の値を持つときは、実際には整数にすぎないことに注意してください。同じ整数値にはいくつかの名前がありますが、値を取得した時点では完全に区別できません。

本当にやりたいこと、おそらくあなたの解析方法に加えて、私には聞こえますが、ToStringWithoutObsoleteメソッドを書いています。これは値を名前にマップすることができますが、時代遅れの属性を持たない値に対してのみ可能です。コード内の任意の場所にtypeof(T).GetField(a.ToString())を使用すると、結果は予測不可能になります。 すべて列挙型の静的フィールドを取得する方が良いでしょう。したがって、たとえば:

var valueToName = typeof(T) 
    .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static) 
    .Where(f => !f.IsDefined(typeof(ObsoleteAttribute), false) 
    .ToDictionary(f => (T) f.GetValue(null), 
        f => f.Name); 
+0

OMG、予期しないターン。私はそうしようとしましょう –

+0

複数の列挙型メンバーが時代遅れでなくても同じ値を持つことができるので、この辞書は必ずしもすべての古い名前を返すわけではありません。その場合のより興味深い辞書はnameToValueです。 – Lazlo

関連する問題