你们都这样做了:
public void Proc(object parameter)
{
if (parameter == null)
throw new ArgumentNullException("parameter");
// Main code.
}
parameter.ThrowIfNull("parameter");
所以我得到了这个扩展的两个实现,我不知道哪个是最好的。
首先:
internal static void ThrowIfNull<T>(this T o, string paramName) where T : class
{
if (o == null)
throw new ArgumentNullException(paramName);
}
第二
internal static void ThrowIfNull(this object o, string paramName)
{
if (o == null)
throw new ArgumentNullException(paramName);
}
您怎么看?
答案 0 :(得分:13)
我倾向于坚持无处不在的Guard
类:
static class Guard
{
public static void AgainstNulls(object parameter, string name = null)
{
if (parameter == null)
throw new ArgumentNullException(name ?? "guarded argument was null");
Contract.EndContractBlock(); // If you use Code Contracts.
}
}
Guard.AgainstNulls(parameter, "parameter");
并且避免扩展object
,加上肉眼观察null
对象上的方法调用似乎没有意义(尽管我知道对扩展方法进行空方法调用是完全有效的)。
至于哪个最好,我也不使用。 他们都有无限递归。我也不打扰保护message参数,使其可选为null。您的第一个解决方案也不支持Nullable<T>
类型,因为class
约束会阻止它。
我们的Guard
课程在我们决定启用代码合同之后也会进行Contract.EndContractBlock()
调用,因为它符合所需的“if-then-throw”结构。
这也是PostSharp aspect的完美候选人。
答案 1 :(得分:5)
我使用internal static void ThrowIfNull<T>(this T o, string paramName) where T : class
。我不会使用internal static void ThrowIfNull(this object o, string paramName)
,因为它可能会进行拳击。
答案 2 :(得分:4)
我会这样做以避免硬编码参数名称。明天它可以改变,然后你还有更多的工作:
public static void ThrowIfNull<T>(this T item) where T : class
{
if (item == null)
return;
var param = typeof(T).GetProperties()[0];
if (param.GetValue(item, null) == null)
throw new ArgumentNullException(param.Name);
}
并称之为:
public void Proc(object parameter)
{
new { parameter }.ThrowIfNull(); //you have to call it this way.
// Main code.
}
性能上升是微不足道的(在我平庸的计算机上,它在25毫秒内运行了100000次),比通常看到的基于表达式的方法快得多
ThrowIfNull(() => resource);
一个here。但如果你不能承受这么大的打击,肯定不要使用它。
您还可以为对象的属性扩展它。
new { myClass.MyProperty1 }.ThrowIfNull();
您可以缓存属性值以进一步提高性能,因为属性名称在运行时不会更改。
答案 3 :(得分:0)
如何使用表达式树(来自Visual Studio Magazine):
test()
}
像这样使用:
using System;
using System.Linq.Expressions;
namespace Validation
{
public static class Validator
{
public static void ThrowIfNull(Expression<Func<object>> expression)
{
var body = expression.Body as MemberExpression;
if( body == null)
{
throw new ArgumentException(
"expected property or field expression.");
}
var compiled = expression.Compile();
var value = compiled();
if( value == null)
{
throw new ArgumentNullException(body.Member.Name);
}
}
public static void ThrowIfNullOrEmpty(Expression<Func<String>> expression)
{
var body = expression.Body as MemberExpression;
if (body == null)
{
throw new ArgumentException(
"expected property or field expression.");
}
var compiled = expression.Compile();
var value = compiled();
if (String.IsNullOrEmpty(value))
{
throw new ArgumentException(
"String is null or empty", body.Member.Name);
}
}
}
答案 4 :(得分:-1)
第二个似乎更优雅的处理方式。在这种情况下,您可以对每个托管对象设置限制。
internal static void ThrowIfNull(this object o, string paramName)
{
if (o == null)
throw new ArgumentNullException(paramName);
}