我似乎陷入了 NullReferenceExceptions 的巨大麻烦
最近我正在开发一个软件,可以解析并显示网站上的 XML 信息。够简单吧?
我收到大量 NullReferenceExceptions。例如,这个方法:
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 循环周围包装一个丑陋的 sin If 以防止异常。
我觉得我只是在泄气的轮胎上贴上创可贴,而不是真正解决问题。我有什么办法可以解决这个问题吗?也许我应该读一本关于编程模式或其他什么的书?
真的,我迷路了。我可能问错了问题。
Recently I'm developing a software that parses and displays XML information from a website. Simple enough right?
I'm getting LOADS of NullReferenceExceptions. For example, this method:
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;
}
}
}
I had to wrap an ugly as sin If around the actual foreach loop in order to prevent an exception.
I feel I'm just putting bandaids on a flat tire instead of actually fixing the problem. Is there any way I can tackle this problem? Maybe a book I should read regarding programming patterns or what not?
Really, I'm lost. I'm probably asking the wrong questions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
听起来好像您不确定如果您的方法中收到错误的参数该怎么办。您现在所做的事情本质上没有任何问题,但更常见的模式是检查方法头部的参数,如果它们不是您所期望的,则抛出异常:
这是一种常见的防御性编程模式 -检查以确保您提供的数据通过基本的健全性检查。
现在,如果您自己显式调用此方法,并且发现此方法在您不期望的情况下接收到 null
list
参数,那么是时候查看调用方法的逻辑了。我自己,当我没有元素时,我更喜欢传递一个空列表,而不是null
,以避免此类特殊情况。It sounds as if you're unsure what to do if you receive bad parameters in your methods. There's nothing inherently wrong with what you're doing now, but the more common pattern is to check parameters in the head of your method, throwing an exception if they're not what you're expecting:
This is a common defensive programming pattern - check to make sure that the data you're provided passes basic sanity checks.
Now, if you're calling this method explicitly yourself, and you're finding this method receiving a null
list
parameter when you're not expecting it, it's time to look at the logic of the calling method. Myself, I prefer to pass an empty list when I have no elements, as opposed tonull
, to avoid special cases such as this.我可能会被“无多重退出”人群否决,但我通常会在方法开始时通过简单的检查来处理这个问题:
这指定了退出条件,然后您无需担心多个级别你的方法中的缩进。仅当您能够接受列表为空或为空的事实时,这才有效 - 在某些情况下可能会发生这种情况。
但我同意 codeka 的观点,因为你需要查看调用代码并确定是否可以从那里改进它。
I'm probably going to get downvoted by the "no multiple exit" crowd but I usually handle that with a simple check right at the beginning of the method:
this specifies the exit conditions and then you don't need to worry about multiple levels of indentation in your method. This only works if you can afford to swallow the fact that your list is null or empty - which can happen in some cases.
But I agree with codeka, in that you need to look at the calling code and work out if you can improve it from there.
看起来防御性编程和参数验证正是您正在寻找的。
正如其他人所说,简单的参数验证对您有用:
或者,如果您厌倦了不断为每个参数编写这样的检查,您可以查看许多开源 .NET 前提条件执行库之一。我喜欢 CuttingEdge.Conditions。
这样,您可以使用如下所示的内容:
但是,设置像上述任一这样的前提条件只会指定您的方法不接受空值。 您的问题仍然存在,因为您将空值传递到方法中!要解决这个问题,您必须检查是什么在调用您的方法,并找出为什么要传入空对象。
It seems like defensive programming and parameter validation is what you're looking for.
As others have said, simple parameter validation would work for you:
Alternatively, if you tire of constantly writing checks like this for each parameter, you could check out one of the many open source .NET precondition enforcement libraries. I am fond of CuttingEdge.Conditions.
That way, you can use something like this:
However, setting up a precondition like either of the above will just specify that your method does not accept nulls. Your problem will still exist in that you are passing nulls into the method! To fix that, you will have to examine what is calling your methods, and working out why null objects are being passed in.
除了抛出 ArgumentNullException 异常之外,还有一种称为“Null Obejct Pattern”的东西,如果您想要传递 null,则可以使用它来指示某些东西不存在,例如,但不想显式检查空值。本质上,它是一个实现相同接口的存根类,但它的方法通常要么是空的,要么返回足以使它们变得复杂的值。
http://en.wikipedia.org/wiki/Null_Object_pattern
对于可以不能轻易地通过不能为空来表达它们的不存在。
As well as throwing ArgumentNullException exceptions there's also something called the "Null Obejct Pattern" which you can use if you want to be passing around a null, to indicate, for example, that something doesn't exist, but don't want to have to explicitly check for nulls. Essentially it's a stub class that implements the same interface, but its methods are usually either empty or return just enough to make them comple.
http://en.wikipedia.org/wiki/Null_Object_pattern
Also useful for value types that can't easily express their non existence, by not being able to be null.
当给出无效输入时,我会提前返回(或提前抛出 InvalidArgumentException)。
例如:
或者,您可以使用通用的空合并模式:
I would return early (or throw an InvalidArgumentException early) when given invalid input.
For example:
Alternatively you can use the general null coalescing pattern:
你确实问错了问题。正确的问题是“null 是否代表无效输入或表示 X 的标志”。
在将非空引用类型添加到语言中并使其成为各种 API 之前,您可以选择在代码中明确说明这一点,或者让空引用异常帮助您找到违反期望的位置,然后修复数据/代码之一方式或其他方式。
You are indeed asking the wrong question. The right question is "does null represent an invalid input or a flag that means X".
Until non-null reference types are added to the language and make their way various API's, you have the choice of making that explicit in the code or letting null reference exceptions help you find where the expectation is violated and then fixing the data/code one way or another.