Omu*_*Omu 397 c# collections
这是一个普遍的问题(但我使用的是C#),最好的方法是什么(最佳实践),对于将集合作为返回类型的方法,是否返回null或空集合?
小智 475
空集合.总是.
这很糟糕:
if(myInstance.CollectionProperty != null)
{
foreach(var item in myInstance.CollectionProperty)
/* arrgh */
}
Run Code Online (Sandbox Code Playgroud)
null
返回集合或可枚举时,最好不要返回. 总是返回一个空的枚举/集合.它可以防止上述废话,并防止您的汽车被您的班级的同事和用户怂恿.
在谈论房产时,请务必将房产设置一次并忘记
public List<Foo> Foos {public get; private set;}
public Bar() { Foos = new List<Foo>(); }
Run Code Online (Sandbox Code Playgroud)
在.NET 4.6.1中,您可以压缩这么多:
public List<Foo> Foos { get; } = new List<Foo>();
Run Code Online (Sandbox Code Playgroud)
在讨论返回枚举的方法时,您可以轻松返回空的枚举而不是null
...
public IEnumerable<Foo> GetMyFoos()
{
return InnerGetFoos() ?? Enumerable.Empty<Foo>();
}
Run Code Online (Sandbox Code Playgroud)
使用Enumerable.Empty<T>()
可以被视为比返回更有效,例如,新的空集合或数组.
Boz*_*zho 88
取决于您的合同和具体案例.通常最好返回空集合,但有时(很少):
null
可能意味着更具体的东西;null
.一些具体的例子:
null
意味着元素丢失,而一个空集合将呈现冗余(可能不正确)<collection />
Jef*_*dge 36
还有一点尚未提及.请考虑以下代码:
public static IEnumerable<string> GetFavoriteEmoSongs()
{
yield break;
}
Run Code Online (Sandbox Code Playgroud)
调用此方法时,C#语言将返回一个空的枚举器.因此,为了与语言设计(以及程序员期望)保持一致,应返回空集合.
Geo*_*voy 30
空对消费者更友好.
有一个明确的方法来组成一个空的可枚举:
Enumerable.Empty<Element>()
Run Code Online (Sandbox Code Playgroud)
Jay*_*Jay 18
在我看来,你应该在上下文中返回语义上正确的值,无论它是什么.一句话说"总是返回一个空集合"对我来说似乎有点过分了.
假设在一个医院系统中,我们有一个功能,应该返回过去5年以前所有住院治疗的清单.如果客户没有去过医院,那么返回一个空列表是很有意义的.但是,如果客户将该部分的准入表格留空,该怎么办?我们需要一个不同的值来区分"空列表"和"无答案"或"不知道".我们可以抛出异常,但它不一定是错误条件,并不一定会使我们脱离正常的程序流程.
我经常对无法区分零和无答案的系统感到沮丧.我有很多次系统要求我输入一些数字,我输入零,我收到一条错误消息,告诉我必须在此字段中输入一个值.我刚做了:我进了零!但是它不会接受零,因为它无法区分它和没有答案.
答复桑德斯:
是的,我假设"人没有回答问题"和"答案为零"之间存在差异.这是我答案最后一段的重点.许多程序无法区分"不知道"与空白或零,这在我看来是一个潜在的严重缺陷.例如,我大约一年前在买房子.我去了一个房地产网站,有很多房子上市,要价为0美元.对我来说听起来很不错:他们免费赠送这些房子!但我确信悲惨的事实是他们只是没有进入价格.在这种情况下,你可能会说,"嗯,显然零意味着他们没有进入价格 - 没有人会免费赠送房屋." 但该网站还列出了各个城镇房屋的平均询价和售价.我不禁想知道平均值是否不包含零,因此某些地方的平均值不正确.即100,000美元的平均值是多少; $ 120,000; 和"不知道"?从技术上讲,答案是"不知道".我们可能真正想要的是110,000美元.但我们可能得到的是73,333美元,这是完全错误的.另外,如果我们在用户可以在线订购的网站上遇到此问题怎么办?(不太适用于房地产,但我相信你已经看到它已经为许多其他产品做了.)我们真的想要"未指定价格"被解释为"免费"吗?
RE有两个独立的功能,"有没有?" 和"如果是这样,它是什么?" 是的,你当然可以这样做,但你为什么要这样做?现在调用程序必须进行两次调用而不是一次.如果程序员未能调用"any"会发生什么?然后直奔"它是什么?" ?该程序是否会返回误导零?抛出异常?返回未定义的值?它会创建更多代码,更多工作和更多潜在错误.
我看到的唯一好处是它使您能够遵守任意规则.这条规则是否有任何优势使得值得顺从它的麻烦?如果没有,为什么要这么麻烦?
回复Jammycakes:
考虑一下实际代码的样子.我知道问题说C#但是如果我写Java的话请原谅.我的C#不是很尖锐,原理是一样的.
返回null:
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
Run Code Online (Sandbox Code Playgroud)
具有单独的功能:
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
Run Code Online (Sandbox Code Playgroud)
它实际上是一行或两行代码,返回null,所以它不会给调用者增加负担,而是更少.
我不知道它是如何造成干旱问题的.这不像我们必须执行两次调用.如果我们总是想在列表不存在时做同样的事情,也许我们可以将处理推送到get-list函数而不是让调用者这样做,因此将代码放入调用者将是DRY违规.但我们几乎肯定不想总是做同样的事情.在我们必须要处理列表的函数中,缺少列表是一个可能会停止处理的错误.但是在编辑屏幕上,如果他们还没有输入数据,我们肯定不想停止处理:我们想让他们输入数据.因此,必须以这种或那种方式在呼叫者级别处理"无列表".而且我们是否使用null返回或单独的函数来执行此操作对于更大的原则没有任何区别.
当然,如果调用者没有检查null,程序可能会因空指针异常而失败.但是如果有一个单独的"得到任何"函数并且调用者没有调用该函数但是盲目地调用"获取列表"函数,那么会发生什么?如果它抛出异常或以其他方式失败,那么,这与它返回null并且没有检查它的情况几乎相同.如果它返回一个空列表,那就错了.您无法区分"我有一个零元素列表"和"我没有列表".当用户没有输入任何价格时,就像返回零价:这是错误的.
我没有看到如何将附加属性附加到集合有帮助.呼叫者仍然需要检查它.这比检查null更好吗?同样,可能发生的最糟糕的事情是程序员忘记检查它,并给出不正确的结果.
如果程序员熟悉null的概念意味着"没有价值",那么返回null的函数并不令人惊讶,我认为任何有能力的程序员都应该听说过,无论他认为这是一个好主意.我认为拥有一个单独的功能更像是一个"惊喜"的问题.如果程序员不熟悉API,当他运行没有数据的测试时,他会很快发现有时候他会返回null.但他怎么会发现另一个函数的存在,除非他发现可能有这样的函数并且他检查文档,并且文档是完整和可理解的?我宁愿有一个函数总是给我一个有意义的响应,而不是我必须知道的两个函数,并记得同时调用它们.
Dav*_*und 10
如果一个空集合在语义上有意义,那就是我更喜欢返回的.返回一个空集合进行GetMessagesInMyInbox()
通信"你的收件箱中确实没有任何消息",而返回null
可能有助于沟通没有足够的数据来说明可能返回的列表应该是什么样子.
返回null可能更有效,因为没有创建新对象.但是,它通常还需要null
检查(或异常处理).
在语义上,null
空列表并不意味着相同的事情.差异是微妙的,在特定情况下,一种选择可能比另一种更好.
无论您的选择如何,请记录下来以避免混淆.
归档时间: |
|
查看次数: |
95382 次 |
最近记录: |