开发者

How to attach a value with two keys

开发者 https://www.devze.com 2023-01-07 14:21 出处:网络
I am using a IDictionary, but it allows one key for one value is there any way or IEnumerable 开发者_Python百科list that I can use to add value with teo keys??

I am using a IDictionary, but it allows one key for one value is there any way or IEnumerable 开发者_Python百科list that I can use to add value with teo keys??

Thanks


you could use anything in the generic Dictionary as key...

for example:

class MyKey /*: IComparable*/ {
   public string Key1 {get;set;}
   public string Key2 {get;set;}
   /* //CompareTo seems to be the wrong thing to implement...
   public int CompareTo(object o) {
      if(!(o is MyKey))
         return -1;
      int k1 = Key1.CompareTo(((MyKey)o).Key1);
      return k1 == 0 ? Key2.CompareTo(((MyKey)o).Key2) : k1;
   }*/
   public override bool Equals(object o) {
      return (o is MyKey) &&
         (Key1 == ((MyKey)o).Key1) &&
         (Key2 == ((MyKey)o).Key2);
   }
   public override int GetHashCode() {
      return Key1.GetHashCode() ^ Key2.GetHashCode();
   }
   //to be very kewl we'll add the (in)equality-op's too...:
   public static bool operator ==(MyKey m1, MyKey m2) {
      return m1.Equals(m2);
   }
   public static bool operator !=(MyKey m1, MyKey m2) {
      return !m1.Equals(m2);
   }
}

Dictionary<MyKey, string> myKewlDictionary...


If you are looking for a way to generate a composite key from two values and you are using .NET 4.0 you can use a Tuple as a key - e.g.

var _myDictionary = new Dictionary<Tuple<int, int>, OtherClass>();
_myDictionary.Add(Tuple.Create(item1.Id, item2.Id), item3);
var item = _myDictionary[Tuple.Create(item1.Id, item2.Id)];


Hmm... Really, I don't know why you need that solution, it seems strange. Anyways, you can use custom IEnumerable class as your key collection. You can find my test example below.

using System;
using System.Collections;
using System.Collections.Generic;

namespace TestApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            IDictionary<IEnumerable, object> dictionary1 = new Dictionary<IEnumerable, object>();
            IEnumerable key11 = new string[] { "key1", "key2" };
            IEnumerable key12 = new string[] { "key1", "key2" };
            dictionary1.Add(key11, new object());
            // Exception doesn't occur because key11 and key12 are not equal objects
            dictionary1.Add(key12, new object());

            IDictionary<KeyCollection<string>, object> dictionary2 = new Dictionary<KeyCollection<string>, object>();
            KeyCollection<string> key21 = new KeyCollection<string>(new string[] { "key1", "key2" });
            KeyCollection<string> key22 = new KeyCollection<string>(new string[] { "key1", "key2" });
            dictionary2.Add(key21, new object());
            // ArgumentEception: An item with the same key has already been added
            dictionary2.Add(key22, new object());
        }

        private class KeyCollection<T> : IEnumerable where T : class
        {
            private IEnumerable<T> m_KeyCollection;

            public KeyCollection() : this(new List<T>())
            {
            }

            public KeyCollection(IEnumerable<T> array)
            {
                if (array == null)
                {
                    throw (new NullReferenceException("'array' parameter must be initialized!"));
                }

                IList<T> list = new List<T>();

                IEnumerator<T> enumerator = array.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    list.Add(enumerator.Current);
                }

                m_KeyCollection = list;
            }

            public IEnumerator GetEnumerator()
            {
                return m_KeyCollection.GetEnumerator();
            }

            public override bool Equals(object obj)
            {
                KeyCollection<T> collection = (obj as KeyCollection<T>);

                if (collection == null)
                {
                    return false;
                }

                IEnumerator<T> enumerator1 = m_KeyCollection.GetEnumerator();
                IEnumerator enumerator2 = collection.GetEnumerator();

                bool moveNext1 = false, moveNext2 = false;

                while (true)
                {
                    moveNext1 = enumerator1.MoveNext();
                    moveNext2 = enumerator2.MoveNext();

                    if (moveNext1 && moveNext2)
                    {
                        T current1 = enumerator1.Current;
                        T current2 = (enumerator2.Current as T);

                        if ((current1 == null) || (current2 == null) || (!current1.Equals(current2)))
                        {
                            return false;
                        }

                        continue;
                    }

                    return ((!moveNext1) && (!moveNext2));
                }
            }

            public override int GetHashCode()
            {
                IEnumerator<T> enumerator = m_KeyCollection.GetEnumerator();

                string stringHash = string.Empty;
                while (enumerator.MoveNext())
                {
                    stringHash += string.Format("_{0}", ((enumerator.Current != null) ? enumerator.Current.GetHashCode().ToString() : "-1"));
                }

                return (string.IsNullOrEmpty(stringHash) ? -1 : stringHash.GetHashCode());
            }
        }
    }
}


If your UserID and SessionID can never collide then you can use them both as hash keys: stuff your Userinfo in the dictionary once with the UserID, once with the SessionID, and in the cases when you only have one or the other, add to the dictionary with the only one you have.

(You may need to be concerned about adding a second key to a Userinfo object; say, if method login has a UserID and is deciding whether it needs to create a new Userinfo object to insert into the dictionary vs looking up a Userinfo object via the UserID, and method returning has already inserted the 'correct' Userinfo object into the dictionary using a SessionID but no UserID, login would incorrectly create a new Userinfo object. This may or may not be an issue for your application.)

If the UserID and SessionID can collide then you could use two dictionaries, and search them sequentially when needed. This might still be cleaner than using one dictionary with two different types of keys.

If you will always have one key and sometimes the other, you could use two different kinds of dictionaries: e.g., one to store UserID -> SessionID, and one for SessionID -> Userinfo; OR, one to store SessionID -> UserID, and one for UserID -> Userinfo. This would let you quickly chain your lookups based on the information available. (It feels more like a relational database.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号