我似乎已经陷入了NullReferenceExceptions的巨大麻烦

最近我正在开发一种解析和显示网站XML信息的软件。 够简单吧?

我正在获取NullReferenceExceptions的LOADS。 例如,这种方法:

private void SetUserFriends(List 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循环以防止exception。

我觉得我只是把绷带放在瘪胎上,而不是实际解决问题。 有什么办法可以解决这个问题吗? 也许我应该读一本关于编程模式的书,或者不是什么?

真的,我迷路了。 我可能会问错误的问题。

听起来好像你不确定如果在方法中收到错误参数该怎么办。 你现在正在做什么并没有什么本质上的错误,但更常见的模式是检查方法头部的参数,如果它们不是你期望的那样抛出exception:

 if (list == null) { throw new ArgumentNullException(list); } 

这是一种常见的防御性编程模式 – 检查以确保您提供的数据通过基本的健全性检查。

现在,如果您自己明确地调用此方法,并且您发现此方法在您不期望它时接收空list参数,则应该查看调用方法的逻辑。 我自己,我更喜欢在没有元素时传递一个空列表,而不是null ,以避免像这样的特殊情况。

我可能会被“无多个出口”的人群所淹没,但我通常会在方法的开头用一个简单的检查来处理它:

 if (list == null || list.Count == 0) return; 

这指定了退出条件,然后您不必担心方法中的多个缩进级别。 这只有在您能够承受列表为空或空的事实时才有效 – 在某些情况下可能会发生这种情况。

但我同意codeka,因为你需要查看调用代码并确定是否可以从那里改进它。

似乎防御性编程和参数validation是您正在寻找的。

正如其他人所说,简单的参数validation对您有用:

 if (list == null) throw new ArgumentNullException("list"); 

或者,如果您厌倦了为每个参数不断编写这样的检查,您可以查看许多开源.NET前提条件强制库中的一个。 我喜欢CuttingEdge.Conditions 。

这样,你可以使用这样的东西:

 Condition.Requires(list, "list").IsNotNull(); 

但是,设置上述任一前提条件只会指定您的方法不接受空值。 您的问题仍然存在,因为您将空值传递给方法! 要解决这个问题,您必须检查调用方法的内容,并确定传入null对象的原因。

除了抛出ArgumentNullExceptionexception之外,还有一些称为“Null Obejct Pattern”的东西,如果你想要传递一个null,你可以使用它来表示,例如,某些东西不存在,但不想拥有显式检查空值。 本质上它是一个实现相同接口的存根类,但它的方法通常是空的或返回足以使它们互补。 http://en.wikipedia.org/wiki/Null_Object_pattern

对于无法表达其不存在的值类型也很有用,因为它们不能为空。

给定无效输入时,我会提前返回(或提前抛出InvalidArgumentException)。

例如:

 private void SetUserFriends(List list) { if (list == null) return; /* Do stuff */ } 

或者,您可以使用常规的空合并模式:

 private void SetUserFriends(List list) { list = list ?? new List(); /* Do Stuff */ } 

你确实在问错误的问题。 正确的问题是“null表示无效输入或表示X的标志”。

在将非空引用类型添加到语言并使其成为各种API的方式之前,您可以选择在代码中明确表示或让空引用exception帮助您找到违反期望的位置,然后修复数据/代码方式或其他。