2

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 
4

3 回答 3

2

给你一些想法:

  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
    

根据我的经验,到处使用字符串是一种让错误蔓延的方法,并且很容易出错(嗯,想知道我是怎么知道的?)。拼写错误太容易了,或者为颜色分配大小,反之亦然。

您是否有理由不能在代码中强输入概念?

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

于 2016-03-29T06:12:04.160 回答
1

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

于 2016-03-29T06:18:10.820 回答
0

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

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

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

于 2019-04-25T16:48:35.907 回答