以下问题的答案是:List<T> or IList<T>似乎总是同意返回接口比返回集合的具体实现更好.但我正在努力解决这个问题.实例化一个接口是不可能的,所以如果你的方法返回一个接口,它实际上仍然返回一个特定的实现.我写了两个小方法来try 这一点:

public static IList<int> ExposeArrayIList()
{
    return new[] { 1, 2, 3 };
}

public static IList<int> ExposeListIList()
{
    return new List<int> { 1, 2, 3 };
}

并在我的测试程序中使用它们:

static void Main(string[] args)
{
    IList<int> arrayIList = ExposeArrayIList();
    IList<int> listIList = ExposeListIList();

    //Will give a runtime error
    arrayIList.Add(10);
    //Runs perfectly
    listIList.Add(10);
}

在这两种情况下,当我try 添加一个新值时,我的编译器不会给我任何错误,但当我try 向数组添加某些内容时,将我的数组公开为IList<T>的方法显然会出现运行时错误.

我的另一个担忧是基于linked question(我的重点)的公认答案:

如果您通过其他人将使用的库公开您的类,you generally want to expose it via interfaces rather than concrete implementations.如果您决定稍后更改类的实现以使用不同的具体类,这将有所帮助.在这种情况下,库的用户将不需要更新他们的代码,因为界面不会改变.

如果你只是在内部使用它,你可能不太在意,使用列表也可以.

想象一下,有人真的用我的ExposeListIlist()方法得到的IList<T>来添加/删除值.一切正常.但是现在,正如答案所示,因为返回接口更灵活,所以我返回数组而不是列表(我这边没问题!),然后他们就要请客了...

TLDR:

1) expose 接口会导致不必要的强制转换吗?这无关紧要吗?

2) 有时,如果库的用户不使用强制转换,当您更改方法时,他们的代码可能会中断,即使该方法仍然完好无损.

我可能想得太多了,但我没有得到普遍的共识,即返回接口比返回实现更可取.

推荐答案

也许这并不是直接回答你的问题,但事实上.NET 4.5+,在设计公共或受保护的API时,我更喜欢遵循以下规则:

  • 如果只有枚举可用,则返回IEnumerable<T>
  • 如果枚举和项目计数都可用,则返回IReadOnlyCollection<T>
  • 如果枚举、项目计数和索引访问可用,请务必返回IReadOnlyList<T>
  • 如果可以枚举、计数、修改,一定要返回ICollection<T>
  • 如果枚举、项目计数、索引访问和修改可用,则返回IList<T>.

最后两个选项假设,该方法不能将数组作为IList<T>实现返回.

.net相关问答推荐

API响应返回null错误. NET MAUI

MSBuild:CopyToOutputDirectory不会将本机DLL复制到输出

如何将 signalR 添加到不同项目中的后台服务?

如何从 tshark 的 stderr 捕获实时数据包计数?

使用 DataDog 收集 OpenTelemetry 跟踪

正则表达式匹配 URL 中的多个子目录

如何为多种文件类型设置 FileSystemWatcher 过滤器?

在 C# 中输入按键

从 byte[] 创建 zip 文件

HttpClient 请求抛出 IOException

为什么 .NET 中没有可序列化 XML 的字典?

大型 WCF Web 服务请求因 (400) HTTP 错误请求而失败

使用只读属性或方法?

如何使用 NUnit(或可能使用另一个框架)测试异步方法?

将 C# 编译为本机?

微软内部 PriorityQueue 中的错误?

如何获取命名空间中的所有类?

C# List<> 按 x 然后 y 排序

实体框架太慢了.我有哪些 Select ?

名称 <...> 不存在于命名空间 clr-namespace <...>