最近,我正在开发一种解析和显示网站XML信息的软件。很简单吧?
我正在获取NullReferenceExceptions的LOADS。例如,这种方法:
private void SetUserFriends(List<Friend> list)
{
int x = 40;
int y = 3;
if (list != null)
{
foreach (Friend friend in list)
{
FriendControl control = new FriendControl();
control.ID = friend.ID;
control.URL = friend.URL;
control.SetID(friend.ID);
control.SetName(friend.Name);
control.SetImage(friend.Photo);
control.Location = new Point(x, y);
panel2.Controls.Add(control);
y = y + control.Height + 4;
}
}
}
我不得不把一个丑陋的包裹作为罪恶如果在实际的foreach循环周围以防止异常。
我觉得我只是把绷带放在轮胎上,而不是实际解决问题。有什么办法可以解决这个问题吗?也许我应该读一本关于编程模式的书,或者不是什么?
真的,我迷路了。我可能会问错误的问题。
答案 0 :(得分:15)
听起来好像你不确定如果在方法中收到错误参数该怎么办。你现在正在做的事情没有任何内在错误,但更常见的模式是检查方法头部的参数,如果它们不是你所期望的那样就抛出异常:
if (list == null)
{
throw new ArgumentNullException(list);
}
这是一种常见的防御性编程模式 - 检查以确保您提供的数据通过基本的健全性检查。
现在,如果您自己明确地调用此方法,并且您发现此方法在您不期望它时接收到空list
参数,那么是时候查看调用方法的逻辑了。我自己,当我没有元素而不是null
时,我宁愿传递一个空列表,以避免出现这种特殊情况。
答案 1 :(得分:4)
我可能会被“无多重出口”人群所淹没,但我通常会在方法开头处通过简单的检查处理:
if (list == null || list.Count == 0) return;
这指定退出条件,然后您不必担心方法中的多个缩进级别。这只有在您能够承受列表为空或空的事实时才有效 - 在某些情况下可能会发生这种情况。
但我同意codeka,因为你需要查看调用代码并确定是否可以从那里改进它。
答案 2 :(得分:2)
似乎你正在寻找防御性编程和参数验证。
正如其他人所说,简单的参数验证对您有用:
if (list == null)
throw new ArgumentNullException("list");
或者,如果您厌倦了为每个参数不断编写这样的检查,您可以查看许多开源.NET前提条件强制库中的一个。我喜欢CuttingEdge.Conditions。
这样,您可以使用以下内容:
Condition.Requires(list, "list").IsNotNull();
但是,设置上述任一前提条件只会指定您的方法不接受空值。 您的问题仍然存在,因为 将空值传递给方法!要解决这个问题,您必须检查调用方法的内容,并确定传入null对象的原因。
答案 3 :(得分:1)
除了抛出ArgumentNullException异常之外,还有一些叫做“Null Obejct Pattern”的东西,如果你希望传递一个null,你可以使用它来指示,例如,某些东西没有'存在,但不希望必须显式检查空值。本质上它是一个实现相同接口的存根类,但它的方法通常是空的或返回足以使它们互补。 http://en.wikipedia.org/wiki/Null_Object_pattern
对于无法表达不存在的值类型也很有用,因为它们不能为空。
答案 4 :(得分:0)
当给出无效输入时,我会提前返回(或提前抛出InvalidArgumentException)。
例如:
private void SetUserFriends(List<Friend> list)
{
if (list == null)
return;
/* Do stuff */
}
或者,您可以使用常规的空合并模式:
private void SetUserFriends(List<Friend> list)
{
list = list ?? new List<Friend>();
/* Do Stuff */
}
答案 5 :(得分:0)
你确实在问错误的问题。正确的问题是“null表示无效输入或表示X的标志”。
在将非空引用类型添加到语言中并使其成为各种API的方式之前,您可以选择在代码中进行显式处理,或者让空引用异常帮助您找到违反期望的位置,然后修复数据/代码这样或那样。