允许 IList 参数为 null 或如果为 null 则抛出异常是否有意义?
Does it make sense to allow IList parameter to be null or throw exception if null?
这是我昨天遇到的情况。我想知道这里的最佳做法是什么。我可以像这样创建一个 class 的实例,或者来自其他地方的参数可以为空:
CustomItemsSourceDialogViewModel itemsSource = new CustomItemsSourceDialogViewModel();
itemsSource.Initialize(null); // I get nullReferenceException
这里是提到的 class 定义:
public class CustomItemsSourceDialogViewModel
{
public void Initialize(IList<string> items)
{
// it doesn't make sense to allow parameter items to be null
// it only makes sense to allow not null items collection
// so we can operate on it.
// if items is null we get system.nullReferenceException
if (items.Count > 0)
// aggregate is a system.linq static method
this.ItemsSource = items.Aggregate((x, y) => x + "\r\n" + y);
}
}
我更愿意让我的 collections / 列表不为空。换句话说 collections 应该有一个默认值空 collections。这样开发人员或用户就不会得到那个讨厌的 NullReferenceException。
关于方法的列表参数,当参数为空时我是否应该抛出异常并通知用户:
public void Initialize(IList<string> items)
{
if( items == null )
throw new Exception("Parameter items is null. It should be a valid list.");
...
另一个解决方案是检查它是否不为空:
public void Initialize(IList<string> items)
{
if (items != null && items.Count > 0)
this.ItemsSource = items.Aggregate((x, y) => x + "\r\n" + y);
}
但是总是检查 if not null 似乎有点尴尬。
您应该从以下角度思考:这是否彻底破坏了交易?如果是,那么此时抛出异常是有意义的,因为它会阻止进一步的操作,但是一个好的做法是尽可能远离异常,除非如前所述它是一个表演障碍。
在您的情况下(据我所知,这是对特定列表功能的包装)为什么您没有像这样内联初始化的默认列表值并让用户添加单个项目或参数。或者,如果它不是交易破坏者,您最终可以检查 null。
public List<string> ItemSource { get; set; } = new List<string>();
添加 TheGeneral 和 Will 所写的内容 - 您永远不想在生产代码中看到 NullReferenceException
。
您需要做的是决定是否希望将 null IList
传递给此方法,更重要的是,如果您可以处理此类情况,则不会破坏业务逻辑.
如果这两个问题的答案都是 "no",那么你应该抛出一个 ArgumentNullException - 因为这个异常以最精确的方式传达了问题 - 该方法期望参数不为空:
public void Initialize(IList<string> items)
{
if( items is null ) // requires c# 7 or higher
{
throw new ArgumentNullException(nameof(items));
}
// rest of the code here
}
但是,如果您的业务逻辑可以在没有 IList
的情况下继续进行,并且预计 null
将发送到此方法,那么您应该在方法内部处理这种情况,而不是抛出异常——异常是针对特殊情况的——所以如果空 IList
与空 IList
具有相同的效果并且预计将被传递到方法中- 它不能被认为是异常的,因此不应触发抛出的异常。
public void Initialize(IList<string> items)
{
// just a shorter way for the same condition - requires c# 6 or higher
if (items?.Any() ?? false)
{
this.ItemsSource = Items.Aggregate((x, y) => x + "\r\n" + y);
} // I like to always use code blocks for conditions etc'. I find it more readable.
}
这是我昨天遇到的情况。我想知道这里的最佳做法是什么。我可以像这样创建一个 class 的实例,或者来自其他地方的参数可以为空:
CustomItemsSourceDialogViewModel itemsSource = new CustomItemsSourceDialogViewModel();
itemsSource.Initialize(null); // I get nullReferenceException
这里是提到的 class 定义:
public class CustomItemsSourceDialogViewModel
{
public void Initialize(IList<string> items)
{
// it doesn't make sense to allow parameter items to be null
// it only makes sense to allow not null items collection
// so we can operate on it.
// if items is null we get system.nullReferenceException
if (items.Count > 0)
// aggregate is a system.linq static method
this.ItemsSource = items.Aggregate((x, y) => x + "\r\n" + y);
}
}
我更愿意让我的 collections / 列表不为空。换句话说 collections 应该有一个默认值空 collections。这样开发人员或用户就不会得到那个讨厌的 NullReferenceException。
关于方法的列表参数,当参数为空时我是否应该抛出异常并通知用户:
public void Initialize(IList<string> items)
{
if( items == null )
throw new Exception("Parameter items is null. It should be a valid list.");
...
另一个解决方案是检查它是否不为空:
public void Initialize(IList<string> items)
{
if (items != null && items.Count > 0)
this.ItemsSource = items.Aggregate((x, y) => x + "\r\n" + y);
}
但是总是检查 if not null 似乎有点尴尬。
您应该从以下角度思考:这是否彻底破坏了交易?如果是,那么此时抛出异常是有意义的,因为它会阻止进一步的操作,但是一个好的做法是尽可能远离异常,除非如前所述它是一个表演障碍。
在您的情况下(据我所知,这是对特定列表功能的包装)为什么您没有像这样内联初始化的默认列表值并让用户添加单个项目或参数。或者,如果它不是交易破坏者,您最终可以检查 null。
public List<string> ItemSource { get; set; } = new List<string>();
添加 TheGeneral 和 Will 所写的内容 - 您永远不想在生产代码中看到 NullReferenceException
。
您需要做的是决定是否希望将 null IList
传递给此方法,更重要的是,如果您可以处理此类情况,则不会破坏业务逻辑.
如果这两个问题的答案都是 "no",那么你应该抛出一个 ArgumentNullException - 因为这个异常以最精确的方式传达了问题 - 该方法期望参数不为空:
public void Initialize(IList<string> items)
{
if( items is null ) // requires c# 7 or higher
{
throw new ArgumentNullException(nameof(items));
}
// rest of the code here
}
但是,如果您的业务逻辑可以在没有 IList
的情况下继续进行,并且预计 null
将发送到此方法,那么您应该在方法内部处理这种情况,而不是抛出异常——异常是针对特殊情况的——所以如果空 IList
与空 IList
具有相同的效果并且预计将被传递到方法中- 它不能被认为是异常的,因此不应触发抛出的异常。
public void Initialize(IList<string> items)
{
// just a shorter way for the same condition - requires c# 6 or higher
if (items?.Any() ?? false)
{
this.ItemsSource = Items.Aggregate((x, y) => x + "\r\n" + y);
} // I like to always use code blocks for conditions etc'. I find it more readable.
}