我有一个有两个HashSet<String>
集合作为私有成员的类。我的代码中的其他类希望能够遍历这些 HashSet 并读取它们的内容。我不想写一个标准的getter,因为另一个类仍然可以做类似的事情myClass.getHashSet().Clear();
有没有其他方法可以将我的HashSets的元素暴露给迭代而不暴露对HashSet本身的引用?我希望能够以与 for-each 循环兼容的方式执行此操作。
7 回答
假设您使用的是 .NET 3.5,另一种自己编写 yield 代码的方法是调用 LINQ 方法。例如:
public IEnumerable<string> HashSet
{
get { return privateMember.Select(x => x); }
}
或者
public IEnumerable<string> HashSet
{
get { return privateMember.Skip(0); }
}
有各种 LINQ 运算符可以像这样使用 - usingSkip(0)
可能是最有效的,因为在初始“跳过 0 值”循环之后,它可能只是其他答案中显示的foreach
/循环。yield return
该Select
版本将为产生的每个项目调用无操作投影委托。但是,这种差异显着的可能性很小 - 我建议您使用任何使代码对您来说最清晰的方法。
暴露一个IEnumerable<T>
属性:
public IEnumerable<whatevertype> MyHashSet {
get {
return this.myHashSet;
}
}
当然,此代码的用户可以将其强制IEnumerable<T>
转换为 aHashSet<T>
并编辑元素,因此为了安全起见(同时会损害性能),您可以这样做:
public IEnumerable<whatevertype> MyHashSet {
get {
return this.myHashSet.ToArray();
}
}
或者:
public IEnumerable<whatevertype> MyHashSet {
get {
foreach(var item in this.myHashSet) {
yield return item;
}
}
}
一种性能更高但对调用者不太方便的保护方法是返回一个IEnumerator<T>
:
public IEnumerator<whatevertype> GetMyHashSetEnumerator() {
return this.myHashSet.GetEnumerator();
}
添加这样的方法/属性以避免暴露实际容器:
public IEnumerable EnumerateFirst()
{
foreach( var item in hashSet )
yield return item;
}
您还可以使用该Select
方法创建一个无法转换回的包装器HashSet<T>
:
public IEnumerable<int> Values
{
get { return _values.Select(value => value);
}
这样可以避免重复_values
两次,就像您使用.ToArray()
.
您还可以提供这样的序列:
public IEnumerable<string> GetHashSetOneValues()
{
foreach (string value in hashSetOne)
yield return value;
}
然后可以在 foreach 循环中调用此方法:
foreach (string value in myObject.GetHashSetOneValues())
DoSomething(value);
这对聚会来说可能有点太晚了,但今天最简单的方法是使用 Linq。而不是写
public IEnumerable<string> GetValues()
{
foreach(var elem in list)
yield return elem;
}
你可以写
public IEnumerable<string> GetValues() => list;
让您的 getter 将 HashSet 公开为 IEnumerable。
private HashSet<string> _mine;
public IEnumerable<string> Yours
{
get { return _mine; }
}
如果泛型类型是可变的,那么它仍然可以修改,但不能从 HashSet 中添加或删除任何项目。