Eam*_*nne 14 .net c# generics immutability
我的代码充满了收藏 - 我想这不是一件不寻常的事情.但是,各种集合类型的使用并不明显,也不是微不足道的.通常,我想使用暴露"最佳"API的类型,并且语法噪音最小.(请参阅返回值数组时的最佳做法,使用列表数组 -可比较问题的最佳做法).有一些指南建议在API中使用哪些类型,但这些在普通(非API)代码中是不切实际的.
例如:
new ReadOnlyCollection<Tuple<string,int>>(
new List<Tuple<string,int>> {
Tuple.Create("abc",3),
Tuple.Create("def",37)
}
)
Run Code Online (Sandbox Code Playgroud)
List这是一个非常常见的数据结构,但以这种方式创建它们会涉及相当多的语法噪音 - 而且它可能很容易变得更糟(例如字典).事实证明,许多列表永远不会改变,或者至少从未扩展.当然会ReadOnlyCollection引入更多的语法噪音,它甚至没有表达我的意思; 毕竟ReadOnlyCollection可以包装一个变异的集合.有时我在内部使用数组并返回一个IEnumerable表示意图.但是大多数这些方法都具有非常低的信噪比; 这对理解代码至关重要.
对于不是公共API 的99%的代码,没有必要遵循框架指南:但是,我仍然需要一个可理解的代码和一个传达意图的类型.
那么,处理使用小型集合传递价值的沼泽标准任务的最佳实践方法是什么? 阵列应该List尽可能优先吗?还有别的吗?什么是最好的方式 - 清洁,可读,合理有效 - 传递这样的小集合?特别是,对于未阅读此问题并且不想阅读大量API文档但仍然了解其意图的未来维护者而言,代码应该是显而易见的.最大限度地减少代码混乱也是非常重要的- 所以这样的事情充其量是可疑的.具有小表面的主要API的罗嗦类型没有错,但不是大型代码库中的一般做法.ReadOnlyCollection
在没有大量代码混乱(例如显式类型参数)的情况下传递值列表的最佳方法是什么,但仍能清楚地传达意图?
编辑:澄清这是关于制作简短明了的代码,而不是关于公共API的.
更新:
\n\n所以,严格来说这并不是什么新鲜事;但这个问题说服了我继续宣布 一个我已经进行了一段时间的开源项目(仍在进行中,但其中有一些有用的东西),其中包括一个IArray<T>界面(和实现,自然),我认为这正是您想要的:一个索引、只读、甚至协变(奖励!)接口。
一些好处:
\n\nReadOnlyCollection<T>,因此它不会将您束缚于特定的实现。ReadOnlyCollection<T>),因此它“确实是”只读的。ArrayBase<T>(也在库中)并覆盖this[int]和Count属性即可。如果这听起来很有希望,请随时查看并告诉我您的想法。
\n\n我并不是 100% 清楚您在哪里担心这种“语法噪音”:在您的代码中还是在调用代码中?
\n\n如果您能够容忍自己的封装代码中的一些“噪音”,那么我建议包装一个T[]数组并公开一个IList<T>恰好是 a 的数组ReadOnlyCollection<T>:
class ThingsCollection\n{\n ReadOnlyCollection<Thing> _things;\n\n public ThingsCollection()\n {\n Thing[] things = CreateThings();\n _things = Array.AsReadOnly(things);\n }\n\n public IList<Thing> Things\n {\n get { return _things; }\n }\n\n protected virtual Thing[] CreateThings()\n {\n // Whatever you want, obviously.\n return new Thing[0];\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n是的,您这边有一些噪音,但这还不错。而且你暴露的界面非常干净。
\n\n另一种选择是创建自己的接口,例如IArray<T>,它包装 aT[]并提供仅获取索引器。然后曝光这一点。这基本上与暴露 a 一样干净T[],但不会错误地传达项目可以通过索引设置的想法。