具有只读项的 ReadOnlyCollection
ReadOnlyCollection with read-only items
我有一个 class,其中包含一个集合 (Collection<MyItem> myItems
)。我希望能够通过 public 属性(如果可能,在 O(1) 中)私下修改此 Collection 并将其 return 设为只读。我正在考虑使用 ReadOnlyCollection
,但问题是项目 (MyItem
) 不是只读的。所以我创建了一个只读包装器 class (ReadOnlyMyItem
)。如何通过方括号运算符使 ReadOnlyCollection
return 包装器 class (ReadOnlyMyItem
) 而无需再次构建整个集合,我希望一切都保持 O(1) .
我正在考虑从 ReadOnlyCollection
(class ReadOnlyMyCollection : ReadOnlyCollection<MyItem>
或 class ReadOnlyMyCollection : ReadOnlyCollection<ReadOnlyMyItem>
)创建一个新的 class,其中 returns 只读包装器 class (ReadOnlyMyItem
) 通过方括号运算符,但方括号运算符未标记为虚拟且 return 类型甚至不是相同或构造函数没有要使用的包装器 class (IList<ReadOnlyMyItem>
) 的 IList
。我应该从头开始构建 class (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;
// ...
}
你可以使用 IReadOnlyList<T>
而不是 ReadOnlyCollection<T>
吗?
IReadOnlyList<T>
仅提供 count
和索引运算符 [index]
(和 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;
}
请注意,我将接口拆分为 IReadOnlyMyItem
和 IWritableMyItem
,但您实际上并不需要 IWritableMyItem
- 您可以省略该接口并写入:
public sealed class WriteableMyItem: IReadOnlyMyItem
{
public int SomeValue { get; set; }
}
相反。为了完整起见,我只包含了 IWritableMyItem
(因为它展示了如何通过使用 new
将 set
引入到只有 get
的接口 属性 中。
根据下面的评论,您可以通过将 IWriteableMyItem
和 WriteableMyItem
设为私有或内部来防止向下转换的可能性。但是请注意,这仍然可以通过反射来规避 - 但我们正在防止事故而不是欺诈。
我有一个 class,其中包含一个集合 (Collection<MyItem> myItems
)。我希望能够通过 public 属性(如果可能,在 O(1) 中)私下修改此 Collection 并将其 return 设为只读。我正在考虑使用 ReadOnlyCollection
,但问题是项目 (MyItem
) 不是只读的。所以我创建了一个只读包装器 class (ReadOnlyMyItem
)。如何通过方括号运算符使 ReadOnlyCollection
return 包装器 class (ReadOnlyMyItem
) 而无需再次构建整个集合,我希望一切都保持 O(1) .
我正在考虑从 ReadOnlyCollection
(class ReadOnlyMyCollection : ReadOnlyCollection<MyItem>
或 class ReadOnlyMyCollection : ReadOnlyCollection<ReadOnlyMyItem>
)创建一个新的 class,其中 returns 只读包装器 class (ReadOnlyMyItem
) 通过方括号运算符,但方括号运算符未标记为虚拟且 return 类型甚至不是相同或构造函数没有要使用的包装器 class (IList<ReadOnlyMyItem>
) 的 IList
。我应该从头开始构建 class (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;
// ...
}
你可以使用 IReadOnlyList<T>
而不是 ReadOnlyCollection<T>
吗?
IReadOnlyList<T>
仅提供 count
和索引运算符 [index]
(和 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;
}
请注意,我将接口拆分为 IReadOnlyMyItem
和 IWritableMyItem
,但您实际上并不需要 IWritableMyItem
- 您可以省略该接口并写入:
public sealed class WriteableMyItem: IReadOnlyMyItem
{
public int SomeValue { get; set; }
}
相反。为了完整起见,我只包含了 IWritableMyItem
(因为它展示了如何通过使用 new
将 set
引入到只有 get
的接口 属性 中。
根据下面的评论,您可以通过将 IWriteableMyItem
和 WriteableMyItem
设为私有或内部来防止向下转换的可能性。但是请注意,这仍然可以通过反射来规避 - 但我们正在防止事故而不是欺诈。