最近,我养成了一种习惯,使用扩展方法提供类似于流的属性,例如下面的示例或另一个示例entity.AssertNotNull()。
public static class GenericHelper
{
public static void AssignOrThrowIfNull<T>(this T obj, ref T assignTo, string paramName)
{
if (obj == null)
throw new ArgumentNullException(paramName, "Unallowed null argument of type: " + typeof(T).FullName);
assignTo = obj;
}
}然后将其用于以下用途:
public class SmtpClient
public SmtpServerAddress Server
{
get { return smtpServer; }
}
private SmtpServerAddress smtpServer;
public SmtpClient(SmtpServerAddress smtpServer)
{
smtpServer.AssignToOrThrow(ref this.smtpServer, "smtpServer");
}而不是
public SmtpClient(SmtpServerAddress smtpServer)
{
if(smtpServer == null)
throw new ArgumentNullException("smtpServer");
}你认为这是可读的吗?这比任何地方的常规检查都要好吗?事实上,我不能真正决定我是否喜欢它,让我紧张,所以我想要一些外部的投入!
更新:
是的,你让我睁开眼睛。希望你会同意我的看法,下面的内容会更令人愉快。我使用表达式是因为我希望在异常中包含尽可能多的信息。
public static class Require
{
public static void That(Expression<Func<bool>> func)
{
if (!func.Compile()())
throw new ContractException("Contract not fulfilled: " + func.Body, func);
}
}至少我认为这使它更加清晰,尽管lambda语法并不好(我不认为smtpServer != null可以推断为表达式)。
Require.That(() => smtpServer != null);
SmtpServer = smtpServer;因为我每次编译表达式,肯定会有一些性能损失。
发布于 2011-07-09 11:09:56
您可能需要查看代码契约,它允许您编写:
Contract.Requires<ArgumentNullException>(smtpServer != null);这清楚地表达了您想要做的事情,并且有一个额外的优点:允许代码契约工具进行额外的静态检查,以检查调用您的方法是否可能违反合同的代码。
发布于 2011-07-08 20:55:50
我认为你的直觉是对的,我不喜欢它,它似乎是过度设计的。检查参数是否为null和抛出异常的一般模式已经很好地建立起来,而且程序员已经习惯了它,这样他们就可以快速地看一眼就能理解它。您的重构版本是不寻常的,因此他们将不得不进入该方法并查看它。
扩展方法总的来说是狂热的,但我不认为这是一个有效的使用方法。
发布于 2011-07-09 10:10:12
不会让代码变短。
对于那些对您的代码不熟悉的人来说,这一点并没有变得更清楚。
如果在扩展方法中有更多的逻辑,则可能是。但在这种情况下-不。
https://codereview.stackexchange.com/questions/3352
复制相似问题