(C#) 迭代只读私有集合成员

发布于 2024-08-27 18:05:46 字数 252 浏览 7 评论 0原文

我有一个类,它有两个 HashSet 集合作为私有成员。我的代码中的其他类希望能够迭代这些 HashSet 并读取它们的内容。我不想编写标准 getter,因为另一个类仍然可以执行诸如 myClass.getHashSet().Clear(); 之类的操作是否有其他方法可以将我的 HashSets 的元素公开给迭代,而无需进行迭代暴露对 HashSet 本身的引用?我希望能够以与 for-each 循环兼容的方式来完成此操作。

I have a class which has two HashSet<String> collections as private members. Other classes in my code would like to be able to iterate over those HashSets and read their contents. I don't want to write a standard getter because another class could still do something like myClass.getHashSet().Clear(); Is there any other way to expose the elements of my HashSets to iteration without exposing the reference to the HashSet itself? I'd love to be able to do this in a way that is compatible with for-each loops.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

雪化雨蝶 2024-09-03 18:05:46

假设您使用的是 .NET 3.5,您自己编写生成代码的一种替代方法是调用 LINQ 方法。例如:

public IEnumerable<string> HashSet
{
    get { return privateMember.Select(x => x); }
}

or

public IEnumerable<string> HashSet
{
    get { return privateMember.Skip(0); }
}

有多种 LINQ 运算符可以像这样使用 - 使用 Skip(0) 可能是最有效的,因为在初始“跳过 0 值”循环之后,它可能只是 <其他答案中显示的 code>foreach/yield return 循环。 Select 版本将为生成的每个项目调用无操作投影委托。然而,这种差异显着的可能性非常小 - 我建议您选择使代码对您来说最清晰的方式。

Assuming you're using .NET 3.5, one alternative to writing the yield code yourself is to call a LINQ method. For example:

public IEnumerable<string> HashSet
{
    get { return privateMember.Select(x => x); }
}

or

public IEnumerable<string> HashSet
{
    get { return privateMember.Skip(0); }
}

There are various LINQ operators which could be used like this - using Skip(0) is probably the most efficient, as after the initial "skip 0 values" loop, it's probably just the foreach/yield return loop shown in the other answers. The Select version will call the no-op projection delegate for each item yielded. The chances of this difference being significant are astronomically small, however - I suggest you go with whatever makes the code clearest to you.

浅沫记忆 2024-09-03 18:05:46

公开 IEnumerable 属性:

public IEnumerable<whatevertype> MyHashSet {
    get {
        return this.myHashSet;
    }
}

当然,此代码的用户可以将该 IEnumerable 转换为 HashSet并编辑元素,因此为了安全起见(同时会损害性能),您可以执行以下操作:

public IEnumerable<whatevertype> MyHashSet {
    get {
        return this.myHashSet.ToArray();
    }
}

或者:

public IEnumerable<whatevertype> MyHashSet {
    get {
        foreach(var item in this.myHashSet) {
            yield return item;
        }
    }
}

一种更高效的保护方法,但对调用者来说不太方便,是返回 IEnumeratorIEnumerator

public IEnumerator<whatevertype> GetMyHashSetEnumerator() {
    return this.myHashSet.GetEnumerator();
}

Expose a IEnumerable<T> property:

public IEnumerable<whatevertype> MyHashSet {
    get {
        return this.myHashSet;
    }
}

Of course, the user of this code can cast that IEnumerable<T> to a HashSet<T> and edit elements, so to be on the safe side (while hurting performance), you can do:

public IEnumerable<whatevertype> MyHashSet {
    get {
        return this.myHashSet.ToArray();
    }
}

or:

public IEnumerable<whatevertype> MyHashSet {
    get {
        foreach(var item in this.myHashSet) {
            yield return item;
        }
    }
}

A more performant method of protection, but less convenient to the caller, is to return an IEnumerator<T>:

public IEnumerator<whatevertype> GetMyHashSetEnumerator() {
    return this.myHashSet.GetEnumerator();
}
面如桃花 2024-09-03 18:05:46

添加这样的方法/属性以避免暴露实际容器:

public IEnumerable EnumerateFirst()
{
     foreach( var item in hashSet )
         yield return item;
}

Add a method/property like this to avoid exposing the actual container:

public IEnumerable EnumerateFirst()
{
     foreach( var item in hashSet )
         yield return item;
}
眼泪都笑了 2024-09-03 18:05:46

您还可以使用 Select 方法创建一个无法转换回 HashSet 的包装器:

public IEnumerable<int> Values
{
    get { return _values.Select(value => value);
}

这可以避免迭代 _values两次,就像使用 .ToArray() 一样,但将实现保持在一个干净的行中。

You can also use the Select method to create a wrapper than can't be cast back to HashSet<T>:

public IEnumerable<int> Values
{
    get { return _values.Select(value => value);
}

This avoids iterating over _values twice, as you would with .ToArray(), but keeps the implementation to a single clean line.

皇甫轩 2024-09-03 18:05:46

这对于聚会来说可能有点太晚了,但今天最简单的方法是使用 Linq。 写而不是写

public IEnumerable<string> GetValues() 
{
    foreach(var elem in list)
        yield return elem; 
}

你可以

public IEnumerable<string> GetValues() => list;

This might be quite a bit too late to the party but the easiest way today would be to use Linq. Instead of writing

public IEnumerable<string> GetValues() 
{
    foreach(var elem in list)
        yield return elem; 
}

you can write

public IEnumerable<string> GetValues() => list;
追我者格杀勿论 2024-09-03 18:05:46

您还可以提供如下序列:

public IEnumerable<string> GetHashSetOneValues()
{
    foreach (string value in hashSetOne)
        yield return value;
}

然后可以在 foreach 循环中调用此方法:

foreach (string value in myObject.GetHashSetOneValues())
    DoSomething(value);

You may also provide a sequence like this:

public IEnumerable<string> GetHashSetOneValues()
{
    foreach (string value in hashSetOne)
        yield return value;
}

This method may then be called within a foreach loop:

foreach (string value in myObject.GetHashSetOneValues())
    DoSomething(value);
时光磨忆 2024-09-03 18:05:46

让您的 getter 将 HashSet 公开为 IEnumerable。

private HashSet<string> _mine;

public IEnumerable<string> Yours
{
    get { return _mine; }
}

如果泛型类型是可变的,那么仍然可以修改它,但不能在 HashSet 中添加或删除任何项目。

Make your getter expose the HashSet as IEnumerable.

private HashSet<string> _mine;

public IEnumerable<string> Yours
{
    get { return _mine; }
}

If the generic type is mutable, then that can still be modified, but no items can be added or removed from your HashSet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文