2

我有一个包含集合(Collection<MyItem> myItems)的类。我希望能够私下修改此 Collection 并通过公共属性将其作为只读返回(如果可能,在 O(1) 中)。我正在考虑使用 a ReadOnlyCollection,但问题是项目 ( MyItem) 不是只读的。所以我创建了一个只读包装类(ReadOnlyMyItem)。如何通过方括号运算符ReadOnlyCollection返回包装类 ( ReadOnlyMyItem) 而无需再次构建整个 Collection,我希望一切都保持 O(1)。

我正在考虑创建一个派生自ReadOnlyCollection( class ReadOnlyMyCollection : ReadOnlyCollection<MyItem> or class ReadOnlyMyCollection : ReadOnlyCollection<ReadOnlyMyItem> ) 的新类,它通过方括号运算符返回只读包装类 ( ReadOnlyMyItem),但是方括号运算符未标记为虚拟并且返回类型甚至不相同或构造函数没有要使用IList的包装类 ( IList<ReadOnlyMyItem>)。ReadOnlyMyCollection我应该从头开始构建类 ( ) 吗?

代码看起来像这样:

public class MyClass
{
    public ReadOnlyCollection<ReadOnlyMyItem> MyItems { get => GetMyItems(); }
    private List<MyItem> myItems;
    // ...

    private ReadOnlyCollection<ReadOnlyMyItem> GetMyItems()
    {
        throw new NotImplementedException();
    }
    // ...
}

public class MyItem
{
    // ...
}

public class ReadOnlyMyItem
{
    private readonly MyItem myItem;
    // ...

    public ReadOnlyMyItem(MyItem myItem) => this.myItem = myItem;
    // ...
}
4

1 回答 1

2

你能侥幸使用IReadOnlyList<T>而不是ReadOnlyCollection<T>吗?

IReadOnlyList<T>仅提供countand 索引运算符[index](and IEnumerable<T>),但如果您只需要这些,您可以编写如下内容:

public interface IReadOnlyMyItem
{
    int SomeValue { get; }
}

public interface IWritableMyItem: IReadOnlyMyItem
{
    new int SomeValue { get;  set; } // Note use of `new`
}

public sealed class WriteableMyItem: IWritableMyItem
{
    public int SomeValue { get; set; }
}

public sealed class MyClass
{
    readonly List<WriteableMyItem> _items = new List<WriteableMyItem>();

    public IReadOnlyList<IReadOnlyMyItem> MyItems() => _items;
}

请注意,我将接口拆分为IReadOnlyMyItemandIWritableMyItem但您实际上并不需要IWritableMyItem- 您可以省略该接口并编写:

public sealed class WriteableMyItem: IReadOnlyMyItem
{
    public int SomeValue { get; set; }
}

反而。我只是IWritableMyItem为了完整性而包括在内(因为它显示了如何通过使用将 a 引入set只有 a 的接口属性)。getnew

根据下面的评论,您可以通过制作IWriteableMyItemWriteableMyItem私有或内部来防止向下转换的可能性。但是请注意,这仍然可以通过反射来规避 - 但我们正在防止事故而不是欺诈。

于 2020-07-24T08:07:53.067 回答