C# Sortable collection which allows duplicate keys

前端 未结 16 2165
旧巷少年郎
旧巷少年郎 2020-11-28 10:06

I am writing a program to set a sequence in which various objects will appear in report. The sequence is the Y position (cell) on Excel spreadsheet.

A demo part of co

16条回答
  •  南笙
    南笙 (楼主)
    2020-11-28 10:37

    The key (pun intended) to this is to create an IComparable-based class that maintains equality and hashing, but never compares to 0 if not equal. This can be done, and can be created with a couple bonuses - stable sorting (that is, values added to the sorted list first will maintain their position), and ToString() can simply return the actual key string value.

    Here's a struct key that should do the trick:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace System
    {
        /// 
        /// Defined in Totlsoft.Util.
        /// A key that will always be unique but compares
        /// primarily on the Key property, which is not required
        /// to be unique.
        /// 
        public struct StableKey : IComparable, IComparable
        {
            private static long s_Next;
            private long m_Sequence;
            private IComparable m_Key;
    
            /// 
            /// Defined in Totlsoft.Util.
            /// Constructs a StableKey with the given IComparable key.
            /// 
            /// 
            public StableKey( IComparable key )
            {
                if( null == key )
                    throw new ArgumentNullException( "key" );
    
                m_Sequence = Interlocked.Increment( ref s_Next );
                m_Key = key;
            }
    
            /// 
            /// Overridden. True only if internal sequence and the
            /// Key are equal.
            /// 
            /// 
            /// 
            public override bool Equals( object obj )
            {
                if( !( obj is StableKey ) )
                    return false;
    
                var dk = (StableKey)obj;
    
                return m_Sequence.Equals( dk.m_Sequence ) &&
                    Key.Equals( dk.Key );
            }
    
            /// 
            /// Overridden. Gets the hash code of the internal
            /// sequence and the Key.
            /// 
            /// 
            public override int GetHashCode()
            {
                return m_Sequence.GetHashCode() ^ Key.GetHashCode();
            }
    
            /// 
            /// Overridden. Returns Key.ToString().
            /// 
            /// 
            public override string ToString()
            {
                return Key.ToString();
            }
    
            /// 
            /// The key that will be compared on.
            /// 
            public IComparable Key
            {
                get
                {
                    if( null == m_Key )
                        return 0;
    
                    return m_Key;
                }
            }
    
            #region IComparable Members
    
            /// 
            /// Compares this Key property to another. If they
            /// are the same, compares the incremented value.
            /// 
            /// 
            /// 
            public int CompareTo( StableKey other )
            {
                var cmp = Key.CompareTo( other.Key );
                if( cmp == 0 )
                    cmp = m_Sequence.CompareTo( other.m_Sequence );
    
                return cmp;
            }
    
            #endregion
    
            #region IComparable Members
    
            int IComparable.CompareTo( object obj )
            {
                return CompareTo( (StableKey)obj );
            }
    
            #endregion
        }
    }
    

提交回复
热议问题