c#如何';如果不为空则返回';在一艘客轮上?
如果不为null或继续执行,是否有一个单行程序返回某个内容,或者如何使该内容成为空? 所有这些都是为了避免在几种方法中复制IF行 初始代码如下:c#如何';如果不为空则返回';在一艘客轮上?,c#,C#,如果不为null或继续执行,是否有一个单行程序返回某个内容,或者如何使该内容成为空? 所有这些都是为了避免在几种方法中复制IF行 初始代码如下: var error = ValidateStuff(someArg); if (error != null) { return error; } DoOtherStuff(); 那么,如何重构它以避免在任何地方都复制粘贴相同的内容呢? 伪代码类似于 ValidateStuff(someArg) ? return ___ : continue;
var error = ValidateStuff(someArg);
if (error != null)
{
return error;
}
DoOtherStuff();
那么,如何重构它以避免在任何地方都复制粘贴相同的内容呢?
伪代码类似于
ValidateStuff(someArg) ? return ___ : continue;
DoSomethingElse();
AndMoreStuff();
-编辑-
一个更简单的例子,为了澄清一些答案和评论中的疑问:
public string Foo(string arg)
{
string fuu = GetMeSomething(arg);
if(fuu != null) return fuu;
ImDoingThings();
return "I did things";
}
如果有这个,那就太棒了:
public string Foo(string arg)
{
ReturnIfNotNull(GetMeSomething(arg));
ImDoingThings();
return "I did things.";
}
当然可以:
在您的代码中:
ValidateStuff(someArg);
DoOtherStuff();
注意:我经常将ValidateStuff
中的通用代码与中的if(DEBUG)[…]else[…]else[…]endif
组合在一起,这样与生产无关的内容就不会最终出现在生产二进制文件中
警告呢 为此,我使用了一些技巧:
public class WarningsHandler : IDisposable
{
private List<WarningErrorBase> errors = null;
// Default handler. Remember to use 'using', or otherwise you'll end up
// with pain and suffering!
public void Dispose()
{
var errors = FetchValidationResults();
if (errors != null && errors.Count > 0)
{
throw new ValidationException(errors);
}
}
// Handler if you have a better idea than using an Exception
public IEnumerable<Error> FetchValidationResults()
{
var errors = this.errors;
this.errors = null;
return errors;
}
public void Warn(bool condition, Func<Warning> errorBuilder)
{
if (condition)
{
if (errors == null) { errors = new List<WarningErrorBase>(); }
errors.Add(errorBuilder());
}
}
public void Error(bool condition, Func<Error> errorBuilder)
{
if (condition)
{
if (errors == null) { errors = new List<WarningErrorBase>(); }
errors.Add(errorBuilder());
throw new ValidationException(FetchValidationResults());
}
}
}
好的,再来一个小把戏。:-) 将不同错误消息与少量开销混合的最后一种方法是使用
屈服返回
。这使您能够返回具有不同行为的多个结果值。空值可以被忽略
首先,我们需要一大堆包装纸:
// We need some base interface that we can use for return values
public interface IResult { }
// We have to wrap normal return values
public class Result<T> : IResult
{
public Result(T result) { this.Value = result; }
public T Value { get; private set; }
}
// A few classes for messages, errors, warnings, ...
public class Message : IResult
{
public Message(string format, params object[] args)
{
this.Text = string.Format(format, args);
}
public string Text { get; private set; }
internal virtual void Handle(List<Message> messages)
{
messages.Add(this);
}
}
public class Error : Message
{
public Error(Exception ex) :
base("Uncaught exception: {0}", ex.Message)
{ }
public Error(string format, params object[] args) :
base(format, args)
{ }
internal override void Handle(List<Message> messages)
{
throw new ValidationException(this.Text);
}
}
// Other wrappers like warnings, etc.
// Wrapping IEnumerable<IResult> is useful too.
我认为最好的验证方法是抛出一个自定义异常。 (CustomException是从Exception类继承的我自己的类) 比如说,, 我在我的业务层中使用它:(在数据库中保存模型或其他东西) 在表示层:
try
{
var model = new someModel{ fill properties of model };
var service = new SomeService();
service.DoSomething(model);
DoOtherStuff();
}
catch(CustomException ex)
{
ShowMessageToUser(ex.Message);
}
注意:我只捕获自定义异常,而不是业务异常
这是我亲爱的验证参数和模型的战争
我希望这能有所帮助。首先,你可能用了错误的方法;您可能会更好地抛出异常,而不是试图返回错误代码 但是。。。您可以使用lambdas使类似于伪代码的东西工作。它会变得混乱(对于泛型会更混乱),但为了完整性和回答您的具体问题:
static Error ReturnIf(Error error,
Func<Error, bool> predicate,
Func<Error> rest)
{
return predicate(error) ? error : rest();
}
static Error Test2(bool someArg)
{
return ReturnIf(ValidateStuff(someArg), error => error != null, () =>
{
DoSomethingElse();
AndMoreStuff();
return null;
});
}
静态错误返回IF(错误,
Func谓词,
Func(休息)
{
返回谓词(错误)?错误:rest();
}
静态错误Test2(bool someArg)
{
返回ReturnIf(ValidateStuff(someArg),error=>error!=null,()=>
{
DoSomethingElse();
AndMoreStuff();
返回null;
});
}
或者,由于您实际上已经说过“如果不为null,则返回”,因此代码应该简化并更加具体:
static Error ReturnIfNotNull(Error error,
Func<Error> rest)
{
return error ?? rest();
}
static Error Test2(bool someArg)
{
return ReturnIfNotNull(ValidateStuff(someArg) () =>
{
DoSomethingElse();
AndMoreStuff();
return null;
});
}
静态错误ReturnIfNotNull(错误,
Func(休息)
{
返回错误??rest();
}
静态错误Test2(bool someArg)
{
return ReturnIfNotNull(ValidateStuff(someArg)(=>
{
DoSomethingElse();
AndMoreStuff();
返回null;
});
}
我并不是说你真的想在你的特殊情况下使用这样的代码。。。尽管对这项技术进行了广泛的探索。这个函数的范围是什么?你们有不同的类,它们都有一个验证然后再执行的功能吗?它们背后有共同的目的吗?你不能,你所能做的就是将代码最小化,省去return语句周围的大括号。如果你主要期望有效输入,你可以使用
EnsureStuffValid(someArg)
不返回任何内容,如果内容无效,则抛出异常。我绝对建议切换到C#-异常中提供的标准错误返回机制。它们不必手动传播到调用堆栈中,这就是您在这里所做的。您可以使ValidateStuff
返回一个布尔值(false
,如果验证失败)。然后可以通过out
或ref
参数返回验证错误,而不是作为函数的返回值<代码>字符串错误;如果(!ValidateStuff(out errors)){return errors;}
Wait,我认为在C#中可以避免的情况下引发异常是个好主意。实际上,我会说老年退休金计划的版本更好,但这就是为什么我要问你对此有何看法。特别是当它是可以恢复的时候。在本例中,只有当代码能够以有意义的方式从错误中恢复时,他的错误列表才会很大。否则,返回一个错误对象而不是抛出一个异常永远都不是一个好主意。@thinklarge exception用于需要异常的东西。在C#中抛出异常的速度相对较慢,这就是为什么引入了int.TryParse
之类的东西。尽管如此,我还是不会回避他们。因此,在验证列表的情况下,我会推迟抛出
,直到我完成所有验证(将其添加到列表中,然后立即抛出整个列表)。@atlaste Ok,因此我的理解是正确的。这是你的回答对OPs post的假设(假设这是一个验证,所以不是一个坏的假设),但是如果他能够恢复到这一点以上,那么他不会返回一个错误,因为他确实是一个更好的解决方案吗?我们在代码中做了一些类似的事情,出现了严重错误,但也发出了警告。我们还希望在返回时向用户提供所有错误,以便用户可以同时解决所有错误。所以我们很少抛出异常,除非我们的代码看到了异常并说“不,不,我不能处理它”。@thinklarge啊,警告。干得好。[添加到
public IEnumerable<IResult> MyMethod()
{
// Delegate validation to somewhere else. You might wrap an IEnumerable<IResult> here:
yield return ValidateStuff(someArg);
// Information messages, etc
yield return new Message("Hello world!");
// You might end up with an Exception you didn't expect...
var tmp = new List<int>();
tmp[2] = 2; // oopz...
// ...
yield return new Result<int>(12); // return 12;
}
int result = MyMethod().Execute<int>();
public class SomeService
{
public void DoSomething(some params or some instance of a model class)
{
Validate(some params or an instance of a model class);
// some other codes such as save data in database or etc ...
}
private void Validate(some params or an instance of a model class)
{
if(something is wrong)
throw new CustomException("X is invalid"); // X is the name of wrong param
}
}
try
{
var model = new someModel{ fill properties of model };
var service = new SomeService();
service.DoSomething(model);
DoOtherStuff();
}
catch(CustomException ex)
{
ShowMessageToUser(ex.Message);
}
static Error ReturnIf(Error error,
Func<Error, bool> predicate,
Func<Error> rest)
{
return predicate(error) ? error : rest();
}
static Error Test2(bool someArg)
{
return ReturnIf(ValidateStuff(someArg), error => error != null, () =>
{
DoSomethingElse();
AndMoreStuff();
return null;
});
}
static Error ReturnIfNotNull(Error error,
Func<Error> rest)
{
return error ?? rest();
}
static Error Test2(bool someArg)
{
return ReturnIfNotNull(ValidateStuff(someArg) () =>
{
DoSomethingElse();
AndMoreStuff();
return null;
});
}