2

次のようなページにフィルターを追加する方法が必要でした。

カタログ/サイズ-ミディアム/カラー-レッド/

一定量のフィルターがあり、すぐに変更される可能性が非常に低いプロパティが含まれています。これらのフィルターを処理するために列挙型を決定しましたが、null、拡張メソッド、およびその他のプロパティを組み込む必要があるため、これは非常に陰湿になりました。

最後に、構造体の使用を提案するこのStackoverflowの回答に出くわしました。これが私が組み込んだものの例です:

    public struct Color
{
    private int id;
    private bool isDef;

    private Color(int value) { id = value; isDef = true; }
    public bool Hasvalue { get { return isDef; } }
    public bool IsNull { get { return !isDef; } }

    public string Name
    {
        get
        {
            switch(id)
            {
                case 0: return "None";
                case 1: return "Black";
                case 2: return "Blue";
                case 3: return "Green";
                case 4: return "Orange";
                case 5: return "Pink";
                case 6: return "Brown";
                case 7: return "White";
                case 8: return "Yellow";
                case 9: return "Gray";
                case 10: return "Purple";
                case 11: return "Red";
                default: return null;
            }
        }
    }

    public string Abbreviation
    {
        get
        {
            switch(id)
            {
                case 1: return "BK";
                case 2: return "BL";
                case 3: return "GR";
                case 4: return "OR";
                case 5: return "PK";
                case 6: return "BN";
                case 7: return "WT";
                case 8: return "YL";
                case 9: return "GY";
                case 10: return "PR";
                case 11: return "RD";
                default: return null;
            }
        }
    }

    public static IEnumerable<Color> GetValues()
    {
        yield return Color.None;
        yield return Color.Black;
        yield return Color.Blue;
        yield return Color.Green;
        yield return Color.Orange;
        yield return Color.Pink;
        yield return Color.Brown;
        yield return Color.White;
        yield return Color.Yellow;
        yield return Color.Gray;
        yield return Color.Purple;
        yield return Color.Red;
    }

    public static Color Parse(string value)
    {
        if (String.IsNullOrEmpty(value))
            return Color.None;
        foreach (var c in GetValues())
        {
            if (String.Equals(c.Name, value, StringComparison.Ordinal))
                return c;
        }
        return Color.None;
    }

    public override bool Equals(object obj)
    {
        if(!(obj is Color))
            return false;
        Color color = (Color)obj;
        return color.Name.Equals(this.Name, StringComparison.Ordinal);
    }

    public static Color None = new Color(0);
    public static Color Black = new Color(1);
    public static Color Blue = new Color(2);
    public static Color Green = new Color(3);
    public static Color Orange = new Color(4);
    public static Color Pink = new Color(5);
    public static Color Brown = new Color(6);
    public static Color White = new Color(7);
    public static Color Yellow = new Color(8);
    public static Color Gray = new Color(9);
    public static Color Purple = new Color(10);
    public static Color Red = new Color(11);
}

これらはうまく機能しますが、何らかの形で正しく感じられません。たとえば、構造体ごとに同じコードを作成する必要がありますが、これは多くのコードのようです。再利用可能なコードを継承し、何らかの方法でデータをインターフェイスに制限する方がはるかに簡単です。

これを行うためのより良い方法はありますか?静的クラスを使用してみましたが、構造体と同様の機能を備えた静的クラスを作成する方法について頭を悩ませることができませんでした。

投稿に絶望的だと思われる場合は申し訳ありませんが、初めてです。

4

1 に答える 1

3

色の列挙型とapprev-colorマッピングの辞書が必要になります

正しいクラスのインポートから始めます。

using System.Collections.Generic;

可能なすべての色を含む列挙型を作成します。

enum Colors : uint 
{
  Black =  0x00000000,
  Blue =   0x0000FF00,
  Green =  0x00FF0000,
  Orange = 0xFFA50000,
  Pink =   0xFFC0CB00,
  Brown =  0xA52A2A00,
  White =  0xFFFFFF00,
  Yellow = 0xFFFF0000,
  Gray =   0x80808000,
  Purple = 0x80008000,
  Red =    0xFF000000
};

注:これは、RGBA [rrggbbaa]を想定しています。ここで、またはRed | Green | Blue | Alphaは、00-FF(0-255)の任意の値にすることができます。

次に、の辞書を使用して、色と値の1対多の関係をマッピングします。

private Dictionary<string, Colors> colorMap = new Dictionary<string, Colors>();
colorMap.Add("None", Colors.None);
colorMap.Add("Black", Colors.Black);
colorMap.Add("BK", Colors.Black);
colorMap.Add("Blue", Colors.Blue);
colorMap.Add("BL", Colors.Blue);
colorMap.Add("Green", Colors.Green);
colorMap.Add("GR", Colors.Green);
colorMap.Add("Orange", Colors.Orange);
colorMap.Add("OR", Colors.Orange);
colorMap.Add("Pink", Colors.Pink);
colorMap.Add("PK", Colors.Pink);
colorMap.Add("Brown", Colors.Brown);
colorMap.Add("BN", Colors.Brown);
colorMap.Add("White", Colors.White);
colorMap.Add("WT", Colors.White);
colorMap.Add("Yellow", Colors.Yellow);
colorMap.Add("YL", Colors.Yellow);
colorMap.Add("Gray", Colors.Gray);
colorMap.Add("Grey", Colors.Gray);
colorMap.Add("GY", Colors.Gray);
colorMap.Add("Purple", Colors.Purple);
colorMap.Add("PR", Colors.Purple);
colorMap.Add("Red", Colors.Red);
colorMap.Add("RD", Colors.Red);

そして、マッピングのための辞書検索方法:

public Color GetColor(string colorName)
{
  Color color = null;
  if (this.colormap.TryGetValue(colorName, out color));
  return color;
}

注:入力タイプと出力タイプが異なるため、プロパティは使用できません。

TryGetValue()は辞書検索を行います。TryGetValue()は、GetValue()よりも優先されます。これは、キーが見つからない場合、何も実行されないためです(デフォルトでは、最初に「color」を設定したものになります。代替メソッド(GetValue())は、失敗時に例外をスローします。捕まる。

ボーナス:

マッピングに別の値を追加しました。見つけられるかどうかを確認してください。値をマッピングする利点は、拡張可能(追加が簡単)です。もろい構造に身を固めることはありません。

免責事項:

私は約1年でC#の行を書いていなかったので、このコードは投稿されたとおりに正確に機能しない可能性があります。うまくいけば、バグがあれば、私は自分の言いたいことの要点をうまく伝えることができました。

アップデート:

RGBA値を列挙型に追加することにしました。まだご存じない方もいらっしゃると思いますが、デフォルトでは、列挙型はintが自動生成される「辞書」のようなものです。タイプを変更して値を定義することにより、使用可能な値(この場合は「辞書」)にキャストできます。

列挙値から色名を取得するのは、キャストするのと同じくらい簡単です。

string colorName = "Gray";
Colors color = GetColor(colorName);
if(colorName != null)
{
  uint colorHex = (uint)color;
}

注:colorHexを印刷しますが、適切なフォーマットを行わないと、整数値(つまり、16進値ではない)のみが表示されます。頭のてっぺんからテキストをフォーマットする方法を思い出せないので、気にするつもりはありません。他の誰かが文字列フォーマットを追加したい場合、私は反対しません。

更新2:逆引き-ルックアップ

public string GetAbbrev(Colors color)
{
  Dictionary<string, Colors> abbrev = this.colorMap.First(abbrev => abbrev.Value == color);
  return abbrev.Key;
}

この方法は逆引きに有効だと思います。LINQ構文を理解していない場合は、すべてのディクショナリエントリをクエリし、キーがメソッドのパラメータと一致する最初のエントリを返します。次に、そのエントリからキーが返されます。

于 2012-04-20T22:28:53.283 に答える