具有键和值的数据结构作为类类型和使用键和索引的访问值

时间:2016-06-10 14:34:40

标签: c# list dictionary collections

我在C#中寻找类似于Dictionary的数据结构,我可以使用索引和键来访问值。该值的类型为Class而不是string。

我正在创建一个类库,我正在尝试创建一个名为Square的方法,该方法从我的值和密钥对数据结构中返回值。但是,如果我将整数参数传递给Item,那么它应该通过使用索引来获取值,如果将字符串类型传递给Item,那么它应该通过使用键来访问值(如在词典中)

注意:我提到了this链接。但是不能使用System.Collections.Specialized.NameValueCollection,因为它只能将字符串存储为值,但我希望类类型为值。我想使用键和索引来访问值。

3 个答案:

答案 0 :(得分:1)

如果非通用集合适合您的需求,您可以使用OrderedDictionary。如果您使用值类型,则期望进行大量的装箱和拆箱。

如果您绝对需要通用版本,则必须自行构建。例如:

public class OrderedDictionary<TKey, TValue>
{
    private Dictionary<TKey, TValue> _innerDictionary = new Dictionary<TKey, TValue>();
    private List<TKey> _keys = new List<TKey>();

    public TValue this[TKey key]
    {
        get
        {
            return _innerDictionary[key];
        }

        set
        {
            if(!_innerDictionary.ContainsKey(key))
            {
                _keys.Add(key);
            }
            _innerDictionary[key] = value;
        }
    }

    public TValue this[int index]
    {
        get
        {
            return _innerDictionary[_keys[index]];
        }

        set
        {
            _innerDictionary[_keys[index]] = value;
        }
    }        

    public void Add(TKey key, TValue value)
    {
        _innerDictionary.Add(key, value);
        _keys.Add(key);
    }

    public void Clear()
    {
        _innerDictionary.Clear();
        _keys.Clear();
    }

    public bool Remove(TKey key)
    {
        if (_innerDictionary.Remove(key))
        {
            _keys.Remove(key);
            return true;
        }
        else
        {
            return false;
        }
    }

}

您可能需要进行更多异常处理,但大多数功能都在这里。此外,如果你想从那里实现IDictionary<TKey,TVale>,那么缺少的成员应该是微不足道的。

答案 1 :(得分:0)

    System.Collections.Generic.Dictionary<TKeyItem, TValueItem> myDictionary =
        new System.Collections.Generic.Dictionary<TKeyItem, TValueItem>();
    var key = new TKeyItem();   //create key object
    var val = new TValueItem(); //create value object
    myDictionary.Add(key, val); //add key value pair to the dictionary
    var valueByKey = myDictionary[key];  // it will return val by key
    var valuebyIndex = myDictionary.Values.ElementAt(0); // it will retun val by index

答案 2 :(得分:0)

更新了测试以删除/添加项目到词典。看起来删除然后向字典添加新项目会导致新项目出现在已删除项目的位置。这使我声称​​使用 Dictionary 执行此任务将起作用 false 。我更愿意留下这个答案。即使它不是一个有效的解决方案,它也可以说明为什么在想要按键和索引访问集合时不应该使用Dictionary解决方案。

using System;
using NUnit.Common;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;

namespace UnitTests
{
    [TestFixture]
    public class UnitTest1
    {
        [Test]
        public void TestMethod1()
        {

            var types = new[] { typeof(int), typeof(float), typeof(Guid), typeof(UnitTest1) };

            Dictionary <Guid, object> dictionary = types.Select(x => Activator.CreateInstance(x)).ToDictionary(y => Guid.NewGuid());

            types.ToList().ForEach(t =>
                Assert.IsTrue(dictionary.Any(x => x.Value.GetType() == t))
            );

            Assert.IsTrue(dictionary.ElementAt(0).Value is int);
            Assert.IsTrue(dictionary.ElementAt(1).Value is float);
            Assert.IsTrue(dictionary.ElementAt(2).Value is Guid);
            Assert.IsTrue(dictionary.ElementAt(3).Value is UnitTest1);

            dictionary.Add(Guid.NewGuid(), Guid.NewGuid());

            Assert.IsTrue(dictionary.ElementAt(4).Value is Guid);

            //Remove the Guid
            dictionary.Remove(dictionary.ElementAt(2).Key);

            //See that the Element at the 2 position is now UnitTest1
            Assert.IsTrue(dictionary.ElementAt(2).Value is UnitTest1);

            //See that the Element at the 1 position is still float
            Assert.IsTrue(dictionary.ElementAt(1).Value is float);

            dictionary.Add(Guid.NewGuid(), new List<Guid>());

            //See that a newly added item is put the end of the dictionary
            Assert.IsTrue(dictionary.ElementAt(4).Value is List<Guid>); //This Assertion Fails. The List<Guid> appears at position 2.
        }
    }    
}

上面的代码创建了各种类型对象的字典,然后根据类型在字典中找到它们。最后,我们将字典元素置于0位置并断言它是int。请注意,未使用字典的键,可能是任何数据类型。