c# NameValueCollection 不同的值

c# NameValueCollection distinct values

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 

给你的一些想法:

  1. NameValueCollection 允许重复值。使用 Dictionary<string, string>.
  2. NameValueCollection 是一个较旧的对象,仅强类型化为 string, stringDictionary更灵活,因为你可以指定类型参数。
  3. 当使用 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 classes 的一种方法如下:

foreach (ProductAttribute attr in attrs) {
   Color color = attr as Color;
   if (color != null) {
      // work with color
   }
}

或者,您可以创建一个 ProductAttributeType 枚举,将其作为参数添加到 ProductAttribute 构造函数中,并在 ProductAttribute 中以只读摘要 属性 公开它=] class。然后你所有的 subclasses 都传递它们是什么类型,你可以很容易地得到正在做的事情的类型 attr.ProductAttributeType == ProductAttributeType.Color 例如。

我不确定您的用例,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

老问题,但我需要类似的东西(在 VB.Net 中,但在 C# 中很容易应用);我正在使用该集合编译 words/word 组和值之间的引用,同时忽略大小写。字典解决方案会覆盖值,只维护最后一个值,并且绑定到列表的字典变得比我喜欢的更麻烦。为了准确了解所要求的内容,我首先使用以下语法添加:

If Not nvc.AllKeys.Contains(name) OrElse Not nvc.GetValues(name).Contains(value) Then nvc.Add(name, value)

大量重复调用相同的键和值不会非常有效,但这可能是我能找到的最简单的方法。这最终变得多余,并且在我的代号中(有时甚至是值)是临时构建的;为了尽可能减少 code/variables 并提高效率(仍然使用这种效率低下的方法),我首先考虑构建一个 Sub 而是创建了这个:

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 使用,并且与 nvc 完全一样,并且可以防止重复值。事实上,这正是所要求的:防止添加重复值的 NameValueCollection