c# - 采用单个项目或列表的 C# 方法
问题描述
我有一个方法现在需要一个 id。我需要添加一个采用 id 列表的方法。我的选择是让其中一种方法像这样调用另一种方法:
void NotifyUsers(List<int> userIds) {//do things}
void NotifyUser(int userId)
{
NotifyUsers(new List<int>{userId})
}
或者我可以将呼叫更改为NotifyUsers(new List<int>{9999}
.
或者我可以使用泛型等。
这里的“最佳实践”是什么?
我知道这有点基于意见的问题,但似乎应该有一个围绕这个的标准,但我找不到它。
解决方案
这里的“最佳实践”是什么?
最佳做法是采用整体方法,特别强调调用者的需求。这并不一定意味着为调用者提供最大的灵活性!这意味着了解调用者的用例。
我个人构建此解决方案的方式是:
// Notice: User, not Users. This notifies a single user.
void NotifyUser(int id)
{
// notify the user
}
void NotifyUsers(IEnumerable<int> ids)
{
foreach(var id in ids)
NotifyUser(id);
}
这向调用者强调,如果您想执行一次,请使用NotifyUser
,并且如果您有任何用户序列(不仅仅是列表),那么您NotifyUsers
使用该序列进行调用。
现在我要问的下一个问题是:调用者是否想要这样做:
NotifyUsers(10, 20, 30);
在这种情况下,我会添加第三个函数:
void NotifyUsers(params int[] ids)
{
NotifyUsers((IEnumerable<int>) ids);
}
这种技术对调用者来说是灵活的,同时确保您的大多数方法都是简单的单行方法。如果 NotifyUser 中存在错误,您只想在一个地方修复它。
这种方法的一个缺点是它NotifyUsers()
变得合法并且是无操作的。有人可能会不小心调用它并认为它正在做某事。在这种情况下,您可能会强制至少有一个:
void NotifyUsers(int id, params int[] ids)
{
NotifyUser(id);
NotifyUsers((IEnumerable<int>) ids);
}
这说明了一个重要的观点:考虑来电者的需求还涉及对你不认识的人进行心理分析,以找出他们会做错什么,然后在它发生之前阻止它。设计让人们自然而然地走向成功的 API很难!
(另外,请注意这些草图省略了错误处理;您可能想要检查序列和数组是否不为空,等等。)
这里的关键是:从了解调用者的需求开始;设计满足他们需求的 API。然后实施它。也就是说,实施选择应该是什么?
这取决于通知一系列用户的工作方式。我上面勾勒的解决方案做了一些假设。他们是:
- “一次”通知一百个用户并不比一次通知一百个用户更有效。
- 如果按顺序通知一个用户失败,正确的做法是停止再通知。
如果这些假设是错误的怎么办?考虑一个更新数据库的 API,昂贵的部分不是更新,而是与数据库建立连接。在这种情况下,您不想写:
void NotifyUser(int id)
{
Connect(); // Expensive
Update(id);
Disconnect();
}
void NotifyUsers(IEnumerable<int> ids)
{
foreach(var id in ids)
NotifyUser(id);
}
因为现在您正在为 100 个用户建立 100 个连接。相反,您想翻转脚本:
void NotifyUser(int id)
{
NotifyUsers(Enumerable.Repeat(id, 1));
}
void NotifyUsers(IEnumerable<int> ids)
{
Connect();
foreach(var id in ids)
Update(id);
Disconnect();
}
请注意,在重写实现时,我没有重写 API;请记住,我们已经为调用者设计了 API ,因此如果此 API 满足他们的需求,请不要更改它!方法是抽象;我们可以更改细节以满足性能要求。(如果我们因为 API 设计问题而无法达到性能目标,那么我们一开始就没有设计满足调用者需求的 API。)
现在错误处理呢?有很多可能性:
- 通知需要尽最大努力。如果序列中的一个通知失败,则捕获异常,吃掉它,然后继续与其他用户一起工作。永远不要通知调用者失败
- 通知需要尽最大努力,但调用者需要了解所有故障。记录异常并重新抛出它们或返回失败报告而不是 void。
- 通知必须是全有或全无。也就是说,如果第十个通知失败,则撤消之前的通知以保持世界一致。这很难。你不能解铃。
等等。再次仔细考虑调用者的需求。他们期望失败时会发生什么?你知道如何编写逻辑来做调用者期望的事情吗?您能否清楚地记录下来,以便调用者知道他们的期望是否得到满足?
推荐阅读
- python - 如何使用 Python 和 BeautifulSoup 在网站的 HTML 代码中查找特定文本?
- docker - wordpress docker 镜像和 nginx 反向代理
- google-app-engine - 除了 Google App Engine,我可以在哪里部署我的项目在 nuxt.js 上?
- linux - 将 Expect 脚本与 Expect/send 一起使用
- r - 如何停止ggplot线图添加填充
- c++ - 无法确定我的 USB 设备的驱动器
- tensorflow - 如何在 TensorFlow 中实现这个操作?
- javascript - 如何使用带有反应原生 AsyncStorage 的 Promise 更改应用程序主题?
- php - 如何不在我的这部分代码中创建一个大的 if 列表?
- android-audiomanager - 如何在 Android 中使用语音以编程方式增加/减少音量