我需要一种向页面添加过滤器的方法,如下所示:
Catalog/Size-Medium/Color-Red/
我有一定数量的过滤器,它们包含的属性不太可能很快改变。为了处理这些过滤器,我决定使用枚举,但这变得非常阴险,因为我需要合并空值、扩展方法和其他属性。
最后我发现了这个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);
}
这些效果很好,但在某些方面感觉不正确。例如,我必须为每个结构编写相同的代码,这看起来像是很多代码。继承可重用代码并以某种方式将数据限制到接口(interface)会容易得多。
有更好的方法吗?我尝试过使用静态类,但无法理解如何构建一个与我的结构具有类似功能的静态类。
抱歉,如果我在发帖时看起来毫无希望,这是我第一次。
最佳答案
您需要一个颜色枚举和一个用于 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) 之间的任何值。
然后使用字典来映射颜色值的一对多关系:
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() 更受欢迎,因为如果它找不到 key ,它不会执行任何操作(默认为您最初设置“颜色”的值)。替代方法 (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 语法,它会查询所有字典条目并返回键与方法参数匹配的第一个条目。然后从该条目返回 key 。
关于c# - 我应该使用静态类还是结构以外的其他东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10253950/