我应该使用静态类还是结构以外的东西?

时间:2012-04-20 21:42:16

标签: c# model-view-controller static filter struct

我需要一种方法来向页面添加过滤器,如下所示:

  

录/大小 - 中等/颜色红/

我有一定数量的过滤器,它们包含的属性不太可能很快改变。为了处理这些过滤器,我决定使用枚举,但这变得非常阴险,因为我需要合并空值,扩展方法和其他属性。

最后,我遇到了Stackoverflow answer,建议使用结构。这是我加入的一个例子:

    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);
}

这些效果很好,但它们在某种程度上感觉不正确。例如,我必须为每个结构编写相同的代码,这看起来像很多代码。继承可重用代码并以某种方式将数据限制到接口会更容易。

有更好的方法吗?我已经尝试过使用静态类但无法理解如何构建一个与我的结构具有类似功能的静态类。

对不起,如果我在发帖时似乎无望,这是我的第一次。

1 个答案:

答案 0 :(得分:3)

你需要一个颜色的枚举和一个apprev颜色映射的字典

从正确的类导入开始:

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]其中或红色|绿色|蓝色| 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())抛出一个需要失败的异常被抓住了。

<强>加成:

我在映射中添加了另一个值,看看是否可以找到它。映射值的好处是,它是可扩展的(易于添加)。你不会把自己锁在一个脆弱的结构中。

<强>声明:

我在大约一年内没有写过一行C#,所以这段代码可能与发布完全不同。希望如果有任何错误,我做了很好的沟通我的意思的要点。

<强>更新

我决定将RGBA值添加到枚举中。如果您还不知道,默认情况下枚举的核心就像一个'字典',其中int是自动生成的。通过更改它的类型并定义值,可以将其强制转换为可用值(在本例中为“字典”)。

从枚举值中获取颜色名称就像投射它一样简单:

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

注意:我会打印colorHex但没有正确的格式化它只会显示整数值(即不是十六进制值)。我不记得如何从头顶做文字格式化,所以我不打扰。如果有人想要添加字符串格式,我不会反对。

更新2:反向查找

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

我认为这种方法应该适用于反向查找。如果您不理解LINQ语法,它将查询所有字典条目并返回键与方法参数匹配的第一个字典条目。然后从该条目返回密钥。