Appearance
HashSet
HashSet 是什么
HashSet<T> 是“唯一元素集合”。它只关心:这个元素有没有出现过。 它不关心顺序,也不能用下标访问。
c
using System.Collections.Generic;
HashSet<int> collectedIds = new();
collectedIds.Add(1001);
collectedIds.Add(1002);
collectedIds.Add(1001); // 重复,不会再加进去
Debug.Log(collectedIds.Count); // 2Add 的返回值很重要
c
bool isNew = collectedIds.Add(1001);
if (isNew)
{
Debug.Log("第一次收集");
}
else
{
Debug.Log("已经收集过了");
}Add 返回 true:真的加进去了。 Add 返回 false:集合里已经有了。
最常用:Contains
c
if (collectedIds.Contains(1001))
{
Debug.Log("这个宝箱已经开过");
}如果你只是想判断“有没有”,HashSet<T> 通常比 List<T> 更合适。
Unity 常见用法
c
HashSet<Enemy> hitTargets = new();
void Hit(Enemy enemy)
{
if (!hitTargets.Add(enemy))
return;
enemy.TakeDamage(10);
}这个适合范围技能:同一个敌人进入多次,只伤害一次。
寻路也常用:
c
HashSet<Vector2Int> visited = new();
if (visited.Contains(cell))
return;
visited.Add(cell);集合运算
c
HashSet<int> a = new() { 1, 2, 3 };
HashSet<int> b = new() { 3, 4, 5 };
a.UnionWith(b); // 并集:1,2,3,4,5
a.IntersectWith(b); // 交集:双方都有的
a.ExceptWith(b); // 差集:移除 b 里有的注意:这些 With 结尾的方法会修改当前集合。想保留原集合,就先复制一份。
HashSet vs List vs Dictionary
List<T>:有顺序、可重复、能用下标。 Dictionary<TKey, TValue>:用 Key 找 Value。 HashSet<T>:只判断元素是否存在,并自动去重。
常见坑
不要依赖 HashSet 的遍历顺序。 不要在 foreach 当前 HashSet 时 Add 或 Remove。 自定义类当元素时,要理解相等规则;常用 int、string、enum、Vector2Int 会更稳。
参考链接Microsoft HashSetHashSet.AddHashSet.ContainsHashSet.UnionWithHashSet.IntersectWithIEqualityComparerUnity Script Serialization Rules