C#代码如下:
NameValueCollection nvc = new NameValueCollection();
nvc.Add("color", "red");
nvc.Add("size", "s");
nvc.Add("color", "red");
nvc.Add("size", "m");
nvc.Add("color", "red");
nvc.Add("size", "l");
//blue
nvc.Add("color", "blue");
nvc.Add("size", "m");
nvc.Add("color", "blue");
nvc.Add("size", "l");
//green
nvc.Add("color", "green");
nvc.Add("size", "s");
nvc.Add("color", "green");
nvc.Add("size", "m");
nvc.Add("color", "green");
nvc.Add("size", "l");
实际结果:
color:red,red,red,blue,blue,green,green,green
size:s,m,l,m,l,s,m,l
希望结果:
color:red,blue,green
size:s,m,l
答案 0 :(得分:2)
有些想法:
NameValueCollection
允许重复值。使用Dictionary<string, string>
。NameValueCollection
是较旧的对象,仅强类型为string, string
。 Dictionary
更灵活,因为您可以指定类型参数。使用Dictionary
时请注意,如果您尝试两次添加相同的密钥,则会出现错误。这可以通过稍微更改语法来解决。而不是Add()
,只需使用索引器:
var myDict = new Dictionary<string, string>();
myDict["color"] = "blue";
myDict["color"] = "blue"; // no harm doing this twice
根据我的经验,在整个地方使用字符串是一种让bug陷入其中的方法,并且很容易出错(嗯,我想知道我怎么知道这个?)。拼错一些东西太容易了,或者为一种颜色指定尺寸,反之亦然。
您是否有理由在代码中强力键入概念?
public abstract class ProductAttribute { }
public sealed class Color : ProductAttribute {
private Color(string value) { Value = value; }
public Value { get; }
public static readonly Blue = new Color("blue");
public static readonly Green = new Color("green");
private static readonly IReadOnlyDictionary<string, Color> _colorDict =
new ReadOnlyDictionary<string, Color>(
new List<Color> {
Blue, Green
}.ToDictionary(color => color.Value, color => color)
);
public static Color GetColor(string value) {
Color color;
_colorDict.TryGetValue(value, out color);
return color;
}
}
然后为尺寸做类似的事情。这只是一个想法,也许不是很灵活(您必须更改代码以添加新值),但它应该向您展示可能的内容。
但看看你现在能做什么:
var attrs = new HashSet<ProductAttribute>;
attrs.Add(Color.Blue);
attrs.Add(Color.Green);
attrs.Add(Color.Blue); // no problem
attrs.Add(Color.GetColor("blue")); // no problem
attrs.Add(Size.Small);
attrs.Add(Size.Medium);
attrs.Add(Size.Medium); // no problem
使用ProductAttribute
类的一种方法是这样的:
foreach (ProductAttribute attr in attrs) {
Color color = attr as Color;
if (color != null) {
// work with color
}
}
或者,您可以创建ProductAttributeType
枚举,将其作为参数添加到ProductAttribute
构造函数中,并将其公开在ProductAttribute
类的只读抽象属性中。然后,所有子类都以它们的类型传递,例如,您可以轻松获取仅执行attr.ProductAttributeType == ProductAttributeType.Color
的类型。
答案 1 :(得分:0)
我不确定您的用例,NameValueCollection
允许重复更好地使用Dictionary
来处理此类情况。
你仍然可以在NameValueCollection
上做同样的事情来获得你想要的结果。
var results = nvc.AllKeys
.GroupBy(g=>g)
.Select(s=>
new
{
key = s.Key,
values = nvc.GetValues(s.Key).Distinct()
});
foreach(var result in results)
{
Console.WriteLine("{0}- {1}", result.key, string.Join(",", result.values) ;
}
工作Example
答案 2 :(得分:0)
老问题,但是我需要类似的东西(在VB.Net中但很容易在C#中应用);我正在使用该集合来编译单词/单词组和值之间的引用,而忽略大小写。字典解决方案会覆盖值,仅保留最后一个值,并且与列表绑定的字典变得比我不愿花力气的维护工作更多。为了确切地得到要问的内容,我首先使用以下语法添加了一种对我有用的方法:
If Not nvc.AllKeys.Contains(name) OrElse Not nvc.GetValues(name).Contains(value) Then nvc.Add(name, value)
大量重复调用相同的键和值将不会非常有效,但这可能是我能找到的最简单的方法。这最终变得多余,并且以我的代码名称(有时甚至是值)被临时构建。为了尽可能减少代码/变量并提高效率(仍然使用这种效率低下的方法),我首先考虑构建一个
Private Class NoDupValueNameValueCollection
Inherits Collections.Specialized.NameValueCollection
Public Overrides Sub Add(name As String, value As String)
If Not MyBase.AllKeys.Contains(name) OrElse Not MyBase.GetValues(name).Contains(value) Then MyBase.Add(name, value)
End Sub
End Class
或C#
private class NoDupValueNameValueCollection : System.Collections.Specialized.NameValueCollection {
public override void Add(string name, string value) {
if (!(base.AllKeys.Contains(name)) || !(base.GetValues(name).Contains(value))) base.Add(name, value);
}
}
现在可以代替nvc并完全使用它,并且可以防止重复值。实际上,这正是所要问的:一个NameValueCollection,可以防止添加重复的值