Skip to content

Instantly share code, notes, and snippets.

@CheeryLee
Created April 21, 2021 22:48
Show Gist options
  • Save CheeryLee/b21bdf52bc6d6db5bb426a4df839bfba to your computer and use it in GitHub Desktop.
Save CheeryLee/b21bdf52bc6d6db5bb426a4df839bfba to your computer and use it in GitHub Desktop.
A set of values with delayed adding and removing. Useful for changing items when iterating over them. The changes will be applied at the next frame.
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// Represents a set of values with delayed adding and removing
/// </summary>
/// <typeparam name="T">The type of elements in the hash set</typeparam>
public class DelayedHashSet<T> : IEnumerable<T>
{
/// <summary>
/// Gets count of items in the set
/// </summary>
public int Count => _items.Count;
private readonly HashSet<T> _items;
private readonly HashSet<T> _itemsToAdd;
private readonly HashSet<T> _itemsToRemove;
/// <summary>
/// Initializes a new instance of the class that is empty
/// </summary>
public DelayedHashSet()
{
_items = new HashSet<T>();
_itemsToAdd = new HashSet<T>();
_itemsToRemove = new HashSet<T>();
}
/// <summary>
/// Initializes a new instance of the class that contains elements copied from the specified collection
/// </summary>
/// <param name="collection">The collection whose elements are copied to the new set</param>
public DelayedHashSet(IEnumerable<T> collection)
{
_items = new HashSet<T>(collection);
_itemsToAdd = new HashSet<T>();
_itemsToRemove = new HashSet<T>();
}
/// <summary>
/// Adds a new item to the set
/// </summary>
/// <param name="item">Required item</param>
public void Add(T item)
{
if (_itemsToRemove.Contains(item))
_itemsToRemove.Remove(item);
if (_itemsToAdd.Contains(item) || _items.Contains(item))
return;
_itemsToAdd.Add(item);
}
/// <summary>
/// Remove an item from the set
/// </summary>
/// <param name="item">Required item</param>
public void Remove(T item)
{
if (_itemsToAdd.Contains(item))
_itemsToAdd.Remove(item);
if (_itemsToRemove.Contains(item) || !_items.Contains(item))
return;
_itemsToRemove.Add(item);
}
/// <summary>
/// Updates the set. Pending items (to add and to remove) should apply.
/// </summary>
public void Update()
{
foreach (var item in _itemsToRemove)
_items.Remove(item);
foreach (var item in _itemsToAdd)
_items.Add(item);
_itemsToRemove.Clear();
_itemsToAdd.Clear();
}
/// <summary>
/// Does set contain an item
/// </summary>
/// <param name="item">Required item</param>
/// <returns>true, if object is in the set, otherwise false</returns>
public bool Contains(T item)
{
return _items.Contains(item);
}
/// <summary>
/// Clears the set. Also pending items will be cleaned.
/// </summary>
public void Clear()
{
_items.Clear();
_itemsToAdd.Clear();
_itemsToRemove.Clear();
}
/// <summary>
/// Returns an enumerator that iterates through an object
/// </summary>
public HashSet<T>.Enumerator GetEnumerator()
{
return _items.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through an object
/// </summary>
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _items.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through an object
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment