perpet

 작업하다보면 foreach 안에서 remove 를 할때가 꼭있다.

속도무시하고 편하게 사용하고 싶을때 사용하면 좋을듯하다.

어떤식으로 구현하는지 의도만 파악하고 자신의 입맛대로 바꾸길 바란다.

 

lib 코드

  1.  
  2. using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
  3. /// 버전 0.1
    /// perpet@hitel.net 구본수
    /// 소스 수정해서 사용하는건 문제 없으나 수정을 하면 반드시 원 제작자에게 수정된 소스를 메일로 보내야합니다. 버그나 개선된것을 꼭알려달라는 뜻입니다.
    ///
    /// 초기 버전이라 버그가 많을수있습니다..
  4.  
  5. namespace Foreach_safe_list
    {
  6.     class SafeCollection<TKey, TValue> //: Dictionary<TKey, TValue>
        {
            //원본리스트
            Dictionary<TKey, TValue> _List = new Dictionary<TKey,TValue>();
  7.         // 임시 add list
            Dictionary<TKey, TValue> _AddList = new Dictionary<TKey, TValue>();
  8.         // 임시 remove list
            List<TKey> _RemoveList = new List<TKey>();
  9.         public Dictionary<TKey, TValue>.KeyCollection Keys
            {
                get { return _List.Keys; }
           
  10.        }
  11.  
  12.         public void Clear()
            {
                if (bForeachCount == 0)
                {
                    _List.Clear();
                }
                else
                {
  13.                 _AddList.Clear();
                    _RemoveList.Clear();
  14.                 foreach(TKey key in _List.Keys)
                        _RemoveList.Add(key);
  15.             }
  16.         }
  17.        public Dictionary<TKey, TValue>.ValueCollection Values {
               get{return _List.Values;}
            }

  18.         public bool ContainsKey(TKey key)
            {
                // 제일 먼저 add list 에서 찾아봐야한다
                bool ret = _AddList.ContainsKey(key);
                if (ret == true)
                    return true;
                // 그다음 remove list 에서 찾아봐야한다.
                if (_RemoveList.Contains(key))
                {
                    return false;
                }
  19.             return _List.ContainsKey(key);
            }
  20.         public bool TryGetValue(TKey key, out TValue value)
            {
                if (bForeachCount == 0)
                {
                    return _List.TryGetValue(key, out value);
                }
                else
                {
                    // 제일 먼저 add list 에서 찾아봐야한다
  21.                 bool ret = _AddList.TryGetValue(key, out value);
                    if (ret == true)
                        return true;
  22.                 // 그다음 remove list 에서 찾아봐야한다.
                    if (_RemoveList.Contains(key))
                    {
                        return false;
                    }

  23.                 return _List.TryGetValue(key, out value);
                }
  24.             //return false;
            }

  25.   public void Add(TKey key ,TValue value)
      {
                if (bForeachCount == 0)
                {
                    _List.Add(key, value);
                }
                else
                {
                    _AddList.Add(key,value);
                }
  26.   }

  27.         public void Remove(TKey key)
            {
                if (bForeachCount == 0)
                {
                    _List.Remove(key);
                }
                else
                {
                    if (_AddList.ContainsKey(key))
                    {
                        _AddList.Remove(key);
                    }
                    else
                    {
                        if (!_List.ContainsKey(key) || _RemoveList.Contains(key))
                        {
                            throw new Exception("dosen't have key");
                        }
  28.                     _RemoveList.Add(key);
                    }
                   
                }
            }
           
            public void StartForeach()
            {
                bForeachCount++;
            }
  29.         public void EndForeach()
            {
                bForeachCount--;
                if (bForeachCount == 0)
                {
  30.                 // remove 먼저해야함
  31.                 foreach (TKey item in _RemoveList)
                    {
                        _List.Remove(item);
                    }
  32.                 _RemoveList.Clear();
  33.                 foreach (KeyValuePair<TKey, TValue> item in _AddList)
                    {
                        _List.Add(item.Key, item.Value);
                    }
                    _AddList.Clear();
                }
            }

  34.   public uint bForeachCount = 0;
  35.         public Dictionary<TKey, TValue>.Enumerator BaseGetEnumerator()
      {
                return _List.GetEnumerator();
      }
  36.   public IEnumerator GetEnumerator()
      {
       return new SafeEnumerator(this);
      }

  37.         class SafeEnumerator : IEnumerator, IDisposable
            {
                SafeCollection<TKey, TValue> _list;
                Dictionary<TKey, TValue>.Enumerator enumerator;
  38.             public object Current { get { return enumerator.Current; } }
                public bool MoveNext() {
  39.                 while (enumerator.MoveNext())
                    {
                        if (_list._RemoveList.Contains(enumerator.Current.Key))
                            continue;
                        return true;
                    }
  40.                 return false;
               
                }
                public void Reset() {
                    //enumerator...Reset();
                }
  41.             public SafeEnumerator(SafeCollection<TKey, TValue> list)
                {
                    _list = list;
                    enumerator = _list.BaseGetEnumerator();
  42.                 _list.StartForeach();
  43.             }
  44.             public void Dispose()
                {
                    _list.EndForeach();
                }
            }

  45.  }
    }

 

test code

 

  1.  sdsd
  2. using System;
    using System.Collections.Generic;
    using System.Text;
  3. namespace Foreach_safe_list
    {
  4.     class buff
        {
            public bool _flag;
            public buff(bool flag)
            {
                _flag = flag;
            }
          
            public void update(){}
          
           
        }
  5.  class Program
     {
  6.  
  7.   static void Main(string[] args)
      {
                SafeCollection<int, buff> a = new SafeCollection<int, buff>();
  8.             a.Add(1,new buff(true));
                a.Add(2,new buff(true));
                a.Add(3,new buff(false));
                a.Add(4,new buff(true));

  9.             foreach (KeyValuePair<int, buff> aaa in a)
       {
                    if( a.ContainsKey(2))
                        a.Remove(2);
  10.                 foreach (KeyValuePair<int, buff> bbb in a)
                    {
                        bbb.Value.update();
                        if (bbb.Value._flag == false)
                            a.Remove(bbb.Key);
                    }
                }
  11.             foreach (KeyValuePair<int, buff> aaa in a)
                {
                    if (a.ContainsKey(2))
                        a.Remove(2);
  12.                 foreach (KeyValuePair<int, buff> bbb in a)
                    {
                        if (!a.ContainsKey(2))
                            a.Add(2, new buff(true));
  13.                 }
  14.             }
  15.             foreach (KeyValuePair<int, buff> aaa in a)
                {
                    Console.WriteLine("{0}", aaa.ToString());
                }
  16.  
  17.   }
     }
    }
  18.  

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.