Google C# 风格指南推理不清楚

Google C# style guide reasoning is unclear

我找到了 Google C# 风格指南和这些要点

For inputs use the most restrictive collection type possible, for example IReadOnlyCollection / IReadOnlyList / IEnumerable as inputs to methods when the inputs should be immutable.

For outputs, if passing ownership of the returned container to the owner, prefer IList over IEnumerable. If not transferring ownership, prefer the most restrictive option.

大约collection我看不懂。

  1. a) 最严格的 collection 是什么意思?我想它们暗示接口的继承如下:IReadOnlyList<T> 继承 IReadOnlyCollection<T> 继承 IEnumerable<T>。那么 IEnumerable 是最严格的吗?

    b) 最重要的是为什么它很重要?任何时候任何人都可以将 above-mentioned collections 转换为 List<T> 并更改内容 - 我认为没有理由选择“最严格的选项”

  2. 他们只需要 return 接口吗?这是否意味着我必须始终将我的 List<T> 转换为 IEnumerable<T> - 这不会误导或影响性能吗?

  3. 他们提到转让所有权。我什么时候想转让所有权,什么时候不想这样做?如果我这样做,为什么

如果您传递所有权 - 您基本上是一个工厂,它创建一些集合,其生命周期由调用者控制:

public class A : IA
{
    public IList<int> Create(){return new List<int>();}
}

如果您不传递所有权,您可以自由地为多个调用者提供相同的集合,因此几乎可以零成本进行缓存:

public class A : IA
{
    private List<int> _someCollection = new List<int>();
    public IEnumerable<int> Create(){return _someCollection; }
}

如果您改为传递 IList,则没有人会再保护此 IList 免受工厂外的意外修改,这将导致缓存损坏。

关于接口...

Google 鼓励您使用接口而不是具体类型,因为有 单元测试 和良好的重构实践,如果您使用具体类型。

例如,如果我想测试在这个具体方法调用上没有更多 RAM 的场景,或者集合在第 6 个元素之后无法枚举,您将如何测试它?或者我希望我的集合在检索前 3 个元素时发挥最佳作用?我只想实现接口:

public class MyOverflowAndPerformantList : IList<int>{/*some bad implementation here*/}

在具体类型的情况下,你实际上会炸毁你的记忆,或者使用一些奇怪的技巧来绕过,因此,这是不切实际的。

1a) 限制最严格的集合确实是 IEnumerable<T>,因为它提供的操作最少。接受尽可能严格的集合作为输入是一种很好的做法,因为它为调用者提供了最大的自由度。它还可以更轻松地推断您的内部实现,因为您知道该集合的自由度较低,例如不可变集合更容易推理。

1b) 这不是真的。 IEnumerable<T> 不一定是列表。它也可以是一个自定义集合,恰好实现了接口,以及许多其他东西。你的演员很可能会失败。

2 ) 如果你 return 一个集合,但你仍然拥有它,你想限制调用者只对集合执行你想要的操作。如果您想继续检查集合的内容,则不应允许调用者对其进行写入。此外,您可以从 return 类型为 IEnumerable<T> 的方法中 return 一个 List<T> 而无需强制转换。

3 ) 转移所有权基本上意味着您已经 return 编辑集合的调用者从现在开始对其负责。您(被调用者)不会关心谁添加到集合中或对再次释放它承担任何责任。在这种情况下,通过将集合公开为其实际类型而不是更具限制性的抽象来为调用者提供完全访问权限是合适的。