是否可以重构这个扩展方法?
我有以下扩展方法:
public static void ThrowIfArgumentIsNull<T>(this T value, string argument)
where T : class
{
if (value == null)
{
throw new ArgumentNullException(argument);
}
}
这是其用法的一个示例....
// Note: I've poorly named the argument, on purpose, for this question.
public void Save(Category qwerty)
{
qwerty.ThrowIfArgumentIsNull("qwerty");
....
}
100% 正常工作。
但是,我不喜欢如何提供变量的名称,只是为了帮助我的异常消息。
我想知道是否可以重构扩展方法,因此可以像这样调用它......
qwerty.ThrowIfArgumentIsNull();
并且它会自动找出变量的名称是“qwerty”,因此使用它作为 ArgumentNullException 的值。
可能的?我假设反射可以做到这一点?
I have the following extension method:
public static void ThrowIfArgumentIsNull<T>(this T value, string argument)
where T : class
{
if (value == null)
{
throw new ArgumentNullException(argument);
}
}
and this is an example of its usage....
// Note: I've poorly named the argument, on purpose, for this question.
public void Save(Category qwerty)
{
qwerty.ThrowIfArgumentIsNull("qwerty");
....
}
works 100% fine.
But, I don't like how I have to provide the name of the variable, just to help my exception message.
I was wondering if it's possible to refactor the extension method, so it could be called like this...
qwerty.ThrowIfArgumentIsNull();
and it automatically figures out that the name of the variable is 'qwerty' and therefore uses that as the value for the ArgumentNullException.
Possible? I'm assuming reflection could do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
“这个扩展方法可以重构一下吗?”
正如其他人已经说过的,如果不使用一些涉及的 AOP(例如包 NullGuard.Fody),您就无能为力,但是您可以为您的版本增添一点趣味,使其更加灵活:
我对各种类型使用了更多方法,例如枚举、字符串等。
您可以在这里找到旧版本的源代码:
https://github.com/CleanCodeX/Common.Shared.Min
或简单地使用Nuget 包,该包会不时更新,因此您只需在需要时更新该包。
https://www.nuget.org/packages/CCX.Common.Shared .分钟/
"Is it possible to refactor this extension method?"
As others already said, there's not much you can do without using some AOP involved (like package NullGuard.Fody), but you can spice up your version a little bit to make it more flexible:
I am using many more Methods for various types, like Enumerables, Strings, etc.
You can find the Sourcecode of an older version here:
https://github.com/CleanCodeX/Common.Shared.Min
or simply use the Nuget package, which will be updated from time to time so you only have to update the package if you want to.
https://www.nuget.org/packages/CCX.Common.Shared.Min/
不,你不能这样做。这固然很好,但如果没有某种 AOP 的参与,这是不可能的。我确信 PostSharp 可以做得很好,希望使用属性,并且在代码契约中它只是:
理想情况下,我想要一个生成代码契约调用的 PostSharp 属性 - 我会在某个时候使用它- 但在那之前,您所拥有的扩展方法是我发现的最好的方法...
(如果我尝试过 PostSharp + 代码契约方法,我肯定会在博客上介绍它,顺便说一句... Mono Cecil 也可能使它变得相当容易。)
编辑:要扩展劳伦特的答案,您可能有:
如果您有很多不可为空的参数,您可能会:
这必须使用反射来计算属性。有一些方法可以避免在每次访问时进行反射,为每个属性构建一个委托,并通常使其变得清晰。我可能会在博客文章中对此进行调查...但这有点令人讨厌,我更喜欢能够仅归因于参数的想法...
编辑:代码实现,以及 博客文章正式制作。恶心,但很有趣。
No, you can't do this. It would be nice, but it's not possible without some sort of AOP getting involved. I'm sure PostSharp can do a nice job, hopefully using attributes, and in Code Contracts it would just be:
Ideally I'd like a PostSharp attribute which generates the Code Contracts call - and I'll play around with that at some point - but until then, the extension method you've got is the best approach I've found...
(If I ever try the PostSharp + Code Contracts approach, I'll certainly blog about it, btw... Mono Cecil might make it reasonably easy too.)
EDIT: To expand on Laurent's answer, you could potentially have:
And if you had lots of non-nullable parameters, you could have:
This would have to use reflection to work out the properties. There are ways that you could avoid doing the reflection on every access, building a delegate for each property and generally making it whizzy. I may investigate this for a blog post... but it's somewhat icky, and I prefer the idea of being able to just attribute the parameters...
EDIT: Code implemented, and blog post duly made. Ick, but fun.
一句话:不。
扩展方法传递一个值。它不知道该值来自哪里,也不知道调用者可能选择将其引用为什么标识符。
In a word: no.
The extension method is passed a value. It has no idea where the value comes from or what identifier the caller may have choosen to refer to it as.
我发现使用代码片段最容易做到这一点。
在您的示例中,我可以输入
tnaqwerty
。这是片段:
I find it easiest to do this using a code snippet.
In your example, I can type
tna<tab>qwerty<enter>
.Here is the snippet:
怎么样:
然后将 ThrowIfArgumentIsNull 定义为
抱歉,我目前没有时间填写详细信息或提供完整的代码。
What about:
then define ThrowIfArgumentIsNull as
sorry I don't have the time to fill in the detail or provide the full code at present.
我建议您宁愿执行以下操作:
在这种情况下使用泛型似乎不会增加任何价值。但至于你最初的问题,我认为这是不可能的。
I would recommend that you rather do the following:
Using generics in this case doesn't seem to add any value. But as to your original question, I don't think that's possible.
我喜欢强制 Lokad 共享库。
基本语法:
如果任何参数为空,这将引发参数名称和类型的异常。
I like Enforce from the Lokad Shared Libraries.
Basic syntax:
This will throw an exception with the parameter name and type if any of the arguments is null.
从 .NET 6 开始,您可以使用以下:
ArgumentNullException.ThrowIfNull(argument);
As of .NET 6, you can use the following:
ArgumentNullException.ThrowIfNull(argument);