使用 YIELD 是返回集合的只读方式吗?

发布于 2024-08-31 08:13:49 字数 622 浏览 10 评论 0原文

我正在编写一个接口,它有一个我想只读的集合属性。我不希望界面的用户能够修改集合。我发现创建只读集合属性的典型建议是将属性的类型设置为 IEnumerable,如下所示:

private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        return this._mylist;
    }
}

但这并不能阻止用户将 IEnumerable 强制转换回 List 并对其进行修改。

如果我使用 Yield 关键字而不是直接返回 _mylist ,则会阻止我的界面的用户修改集合。我这么认为是因为这样我只是一一返回对象,而不是实际的集合。

 private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        foreach(string str in this._mylist)
        {
            yield return str;
        }
    }
}

I'm writing an interface which has a collection property which I want to be read only. I don't want users of the interface to be able to modify the collection. The typical suggestion I've found for creating a read only collection property is to set the type of the property to IEnumerable like this:

private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        return this._mylist;
    }
}

Yet this does not prevent the user from casting the IEnumerable back to a List and modifying it.

If I use a Yield keyword instead of returning _mylist directly would this prevent users of my interface from being able to modify the collection. I think so because then I'm only returning the objects one by one, and not the actual collection.

 private List<string> _mylist;
public IEnumerable<string> MyList
{
get
    {
        foreach(string str in this._mylist)
        {
            yield return str;
        }
    }
}

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

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

发布评论

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

评论(5

墨落成白 2024-09-07 08:13:49

这是防止类的用户强制转换回列表并访问成员的合理方法。另一种选择是使用 _mylist.AsReadOnly(),它返回ReadOnlyCollection

但是,我建议不要担心用户如何通过转换为其他内部类型来“破坏”您的 API。如果您放置 IEnumerable 的公共 API,这就是最终用户将(或应该)使用的 - 而不是尝试转换为 List。试图阻止用户做一些不适当的事情并破坏你的 API,这样充其量也是有问题的,特别是因为你无法阻止所有不适当的使用。

This is a reasonable way to prevent users of your class from casting back to a List and accessing members. Another option is to use _mylist.AsReadOnly(), which returns a ReadOnlyCollection<T>.

However, I would recommend not worrying about how users can "break" your API by casting to other, internal types. If you put a public API of IEnumerable<T>, this is what an end user will (or should) use - not trying to cast to a List<T>. Trying to prevent a user from doing something inappropriate and breaking your API like this is problematic at best, especially since you can't prevent all inappropriate usages.

与往事干杯 2024-09-07 08:13:49

是的,它是不可改变的。

但是,您应该使用 ReadOnlyCollection< /a> 相反。

例如:

MyClassName() {  //(Constructor)
    MyList = new ReadOnlyCollection<string>(_myList);
}

private List<string> _mylist;
public ReadOnlyCollection<string> MyList { get; private set; }

Yes, it is immutable.

However, you should use a ReadOnlyCollection<string> instead.

For example:

MyClassName() {  //(Constructor)
    MyList = new ReadOnlyCollection<string>(_myList);
}

private List<string> _mylist;
public ReadOnlyCollection<string> MyList { get; private set; }
流心雨 2024-09-07 08:13:49

是的,这有效。但这不是唯一的方法。这是在 .NET 3.5 中工作的另一种方法:

public IEnumerable<string> MyList
{
    get { return _myList.Skip(0); }
}

取自此 问题它还显示了您可以做到这一点的其他一些方法。

(使用 Google 找到)。

Yes, that works. It's not the only way though. Here's another way that works in .NET 3.5:

public IEnumerable<string> MyList
{
    get { return _myList.Skip(0); }
}

Taken from this question which also shows some other ways you could do it.

(Found using Google).

你与昨日 2024-09-07 08:13:49

如果使用您的类的代码具有完全信任,则它始终可以反映并访问私有字段。这是相当不礼貌的,但转换返回值也只是稍微好一点。如果用户转换你的财产并破坏状态,那么这是他们自己的错。

直接将列表实例作为 IEnumerable 返回的一个优点是 LINQ 可以优化对 ElementAt() 或 Count() 等方法的访问,而不会违反 IEnumerable 的基本约定(因为这两种方法也可以通过枚举来完成)。

If the code using your class has full trust, it could always Reflect and access the private field anyway. It would be rather impolite, but casting the return value is only marginally better. If a user casts your property and corrupts state, it's their own fault for doing so.

One advantage of returning the list instance directly as IEnumerable is that LINQ can optimize access for methods like ElementAt() or Count(), without violating the fundamental contract of IEnumerable (since either could also be accomplished by enumeration).

无法回应 2024-09-07 08:13:49

是的,生成的序列将是只读的。它还具有延迟执行的优点,因此在某些客户端代码枚举序列中的项目之前,不会真正评估循环(尽管如果在客户端代码尝试枚举内部集合之前更改内部集合,这可能会产生意外的后果) 。

Yes, the resulting sequence will be read-only. It also has the advantage of deferred execution, so the loop won't actually be evaluated until some client code enumerates the items in the sequence (although this can have unexpected consequences if the internal collection is changed before the client code tries to enumerate it).

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