Google C#样式指南的推理尚不清楚

问题描述

我找到了Google C#样式指南以及这些要点

对于输入,应使用限制性最强的集合类型,例如当输入应为不可变时,例如IReadOnlyCollection / IReadOnlyList / IEnumerable作为方法的输入。

对于输出,如果将返回的容器的所有权传递给所有者,则首选IList而不是IEnumerable。如果不转让所有权,请选择限制性最强的选项。

关于我无法理解的收藏集。

  1. a)关于最具限制性的收藏是什么意思?我想它们隐含了如下的接口继承:IReadOnlyList<T>继承了IReadOnlyCollection<T>,后者继承了IEnumerable<T>。所以IEnumerable是限制性最强的一个

    b)最重要的是为什么这很重要?任何人都可以随时将上述集合投放到List<T>并更改内容-我认为没有理由选择“最严格的选择”

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

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

解决方法

1a)限制性最强的集合的确是IEnumerable<T>,因为它提供的操作最少。最好接受限制最大的集合作为输入,因为它为呼叫者提供了最大的自由度。由于您知道集合具有较少的自由度,例如不可变集合的原因更容易推断。

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

2)如果返回一个集合,但您仍然拥有它,则希望限制调用方仅对集合执行所需的操作。如果要继续检查集合的内容,则不应允许调用者对其进行写入。另外,您可以从返回类型为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鼓励您使用接口而不是具体类型,因为存在诸如 Unit Testing 和良好的重构实践之类的东西,如果您使用具体类型,这实际上是无法管理的。

例如,如果我要测试这种具体方法调用中没有更多RAM的情况,或者说第6个元素后无法枚举集合,那么将如何测试呢?或者我希望我的收藏集在检索前三个元素时表现最佳?我只是实现接口:

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

在使用具体类型的情况下,您实际上会炸毁内存,或者使用一些怪异的技巧来解决问题,因此这是不切实际的。