.net 可以重构这个扩展方法吗?
我有以下扩展方法:.net 可以重构这个扩展方法吗?,.net,extension-methods,.net,Extension Methods,我有以下扩展方法: public static void ThrowIfArgumentIsNull<T>(this T value, string argument) where T : class { if (value == null) { throw new ArgumentNullException(argument); } } 工作100%良好 但是,我不喜欢我必须提供变量的名称,只是为了帮助我的异常消息 我想知道是否有
public static void ThrowIfArgumentIsNull<T>(this T value, string argument)
where T : class
{
if (value == null)
{
throw new ArgumentNullException(argument);
}
}
工作100%良好
但是,我不喜欢我必须提供变量的名称,只是为了帮助我的异常消息
我想知道是否有可能重构扩展方法,所以可以这样调用它
qwerty.ThrowIfArgumentIsNull();
它会自动计算出变量的名称是'qwerty',因此使用它作为ArgumentNullException的值
可能吗?我假设反射可以做到这一点?不,你不能这样做。这会很好,但如果没有某种AOP的参与,这是不可能的。我相信PostSharp可以做得很好,希望使用属性,在代码契约中它只是:
Contract.Requires(qwerty!=null);
理想情况下,我想要一个生成代码契约调用的PostSharp属性——我会在某个时候处理它——但在此之前,您拥有的扩展方法是我找到的最好的方法
(如果我曾经尝试过PostSharp+代码契约的方法,我肯定会在博客上写下它,顺便说一句……可能也会让它变得相当简单。)
编辑:要扩展Laurent的答案,您可能有:
new{qwerty}.CheckNotNull();
如果你有很多不可为空的参数,你可以:
new{qwerty,uiop,asdfg}.CheckNotNull();
这必须使用反射来计算属性。有一些方法可以避免在每次访问时进行反射,为每个属性构建一个委托,并通常使其变得时髦。我可能会调查这篇博文。。。但这有点令人讨厌,我更喜欢能够将参数属性化的想法
编辑:代码已执行,并已正式生成。是啊,但很有趣。一句话:不
向扩展方法传递一个值。它不知道该值来自何处,也不知道调用方可能选择将其称为什么标识符。我建议您执行以下操作:
public static void ThrowIfArgumentIsNull(this object value, string argument)
{
if (value == null)
{
throw new ArgumentNullException(argument);
}
}
在这种情况下使用泛型似乎没有增加任何价值。但是关于你最初的问题,我认为那是不可能的
另请参见以获取完整的
解决方案与
回答
那么:
public void Save(Category qwerty)
{
ThrowIfArgumentIsNull( () => qwerty );
qwerty.ThrowIfArgumentIsNull("qwerty");
// ....
}
然后将Throwifargumentisnall定义为
public static void ThrowIfArgumentIsNull(Expression<Func<object>> test)
{
if (test.Compile()() == null)
{
// take the expression apart to find the name of the argument
}
}
公共静态无效throwifargumentisnall(表达式测试)
{
if(test.Compile()()==null)
{
//将表达式拆分以查找参数的名称
}
}
很抱歉,我目前没有时间填写详细信息或提供完整的代码。我发现使用代码片段最容易做到这一点 在您的示例中,我可以键入
tnaqwerty
以下是片段:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Check for null arguments</Title>
<Shortcut>tna</Shortcut>
<Description>Code snippet for throw new ArgumentNullException</Description>
<Author>SLaks</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>Parameter</ID>
<ToolTip>Paremeter to check for null</ToolTip>
<Default>value</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$");
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
检查空参数
tna
抛出新ArgumentNullException的代码段
渣
膨胀
周边地区
参数
检查空值的参数
价值
我喜欢看电视
基本语法:
Enforce.Arguments(() => controller, () => viewManager,() => workspace);
如果任何参数为null,这将引发参数名称和类型异常。另请参见Check-blogged:)我认为这是一个非常简单问题的非常困难的解决方案。。。如果您使用的是Visual Studio,则可以使用代码段使此操作非常简单;)@Jeroen:您似乎认为问题在于类型,而不是防止重构,并将代码中的积垢量保持在最低限度。另请参见,您不需要lambda中的
return
部分。使用泛型允许方法排除值类型。注意where T:class
我读了你的博客文章,你真的不必经历所有的喧嚣。只需实现一个不带参数的ThrowIfNull()
方法,让堆栈跟踪开发人员在堆栈上走一走,找出哪个参数为null。只是想:)@RCIX,当抛出ArgumentNullException时,需要说出参数名。如果OP不关心标准,那么这就不是问题。请参阅API设计指南:@Jared:我查看了引发和处理错误部分以及ArgumentNullException类,但没有看到任何提及。
Enforce.Arguments(() => controller, () => viewManager,() => workspace);