C#要么返回false,要么什么也不做

C#要么返回false,要么什么也不做,c#,.net,if-statement,return,C#,.net,If Statement,Return,我想知道是否有一种方法不必重复相同的if构造,而是调用StatusCheck()。当它成功时,它不能返回true。有人知道这个问题更好的标题吗 我会将“Do stuff”注释表示的代码重构为方法。调用这些方法并捕获异常或检查这些方法的返回值(可能是当前状态),而不是重复调用GetStatus() 另外,我不明白为什么一个名为GetStatus()的方法会有一个ref参数,该参数似乎会被该方法用当前状态更新?如果您必须使用GetStatus()方法,我希望GetStatus()不使用任何参数,而是

我想知道是否有一种方法不必重复相同的if构造,而是调用StatusCheck()。当它成功时,它不能返回true。有人知道这个问题更好的标题吗


我会将“Do stuff”注释表示的代码重构为方法。调用这些方法并捕获异常或检查这些方法的返回值(可能是当前状态),而不是重复调用
GetStatus()

另外,我不明白为什么一个名为
GetStatus()
的方法会有一个
ref
参数,该参数似乎会被该方法用当前状态更新?如果您必须使用
GetStatus()
方法,我希望
GetStatus()
不使用任何参数,而是实际返回当前状态


如果您选择允许这些方法抛出异常,那么请小心不要在抛出这些异常时开始应用真正的逻辑-。

根据您希望的严重程度,您可以为它构建某种操作队列,从而打破方法中的“do stuff”

protected delegate void DoStuffDelegate(ref {TYPE} statusToCheck);

bool Enable()
{
  List<DoStuffDelegate> stuffToDo = new ...
  stuffToDo.Add(myFirstMethod);
  stuffToDo.Add(mySecondMethod);
  foreach(var myDelegate in stuffToDo)
  {
    if(!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; }
    myDelegate(ref status);
  }
}
受保护的委托void DoStuffDelegate(ref{TYPE}statusToCheck);
bool Enable()
{
列表stuffToDo=新建。。。
添加(myFirstMethod);
添加(mySecondMethod);
foreach(stuffToDo中的var myDelegate)
{
如果(!GetStatus(ref status)){Trace.WriteLine(“错误”);返回false;}
myDelegate(参考状态);
}
}

无论是好的还是坏的C#都不允许任何其他构造(如预处理器定义或我们在C++中得到的构造)。

您可以创建一个
CheckStatus()
方法,如果状态无效则抛出异常,然后在
Enable()
方法中处理该异常:

public void CheckStatus(int status)
{
    if (!IsValidStatus(status)) {
        throw new InvalidStatusException(status);
    }
}

public bool Enable()
{
    try {
        CheckStatus(status);
        // do stuff

        CheckStatus(status);
        // do more stuff

        CheckStatus(status);
        // do even more stuff

        // 6 more times the above

        return true;

    } catch (InvalidStatusException) {
        Trace.WriteLine("Error");
        return false;
    }
}

您可以使用异常,并让异常向上传播

void GetStatusAndException(ref Status) {
    if (!GetStatus(ref status))) Throw new Exception("Status exception");
}
如果您不希望出现例外,那么 对此您无能为力,除了将除返回之外的所有内容都放入方法:

bool GetStatusAndTrace(ref Status) {
    bool result = GetStatus(ref status))
    if (!result) Trace.WriteLine("Error");
    return result;
}

bool Enable()
{
    if (!GetStatusAndTrace(ref status))  return false; 
    // do stuff

    if (!GetStatusAndTrace(ref status))  return false; 
    // do more stuff

    if (!GetStatusAndTrace(ref status)) return false; 
    // do even more stuff

    // 6 more times the above

    return true;
}

将代码包装在try-catch块中,并重写GetStatus()以在出错时引发异常。如果您想照章办事,请实现您自己从System.exception继承的异常。然后,如果以后需要该信息,您还可以将“status”属性添加到异常中(但是,您的代码示例没有这样指示)

大概是这样的:

bool Enable()
{
    try
    {
        GetStatus(ref status);
        // do stuff

        GetStatus(ref status);
        // do more stuff

        GetStatus(ref status);
        // do even more stuff

        // 6 more times the above
        return true;
    }
    catch (Exception ex)
    {
        Trace.WriteLine("Error"); 
        return false;
    }
}

正如我所说,抛出和捕获的异常实际上应该是一个自定义异常,但上面的操作会起作用。

让我们看看我是否正确理解您的意思

您可以使用规范设计模式:

与使用harcoded验证不同,您应该使用类似于上述设计模式的实现,因为它为您提供了一种针对对象状态添加规则的更可扩展的方法

例如,您可以定义一个规范“StatusSpecification”,它“用于验证状态是否正确”。结果可能是布尔值

一个坏规则求值器将获得该布尔结果并执行所需的决策(抛出异常?尝试恢复?结束应用程序?只是通知用户错误?报告错误?)


总结:您需要有一些“规范加载器”,并根据加载的对象类型规则执行对象状态。最后,在本例中,您将在一行中计算该状态(从使用者的角度来看),布尔结果可能是您的属性标志。

一个可能的解决方案是为您正在使用的API创建一个“健全”包装器:

class Wrapper
{
    public void DoStuff() // Add static modifiers, parameters and return values as necessary
    {
        API.DoStuff();
        CheckStatus();
    }

    public void DoSomeOtherStuff()
    {
        API.DoSomeOtherStuff();
        CheckStatus();
    }

    private void CheckStatus()
    {
        Status status = default(Status);
        if(!GetStatus(ref status)) throw new InvalidStatusException();
    }
}
只需做一点工作,但它可以让您的客户端代码更具可读性:

bool Enable()
{
    try
    {
        Wrapper.DoStuff();
        Wrapper.DoSomeMoreStuff();
        return true;
    }
    catch(InvalidStatusException)
    {
        Trace.WriteLine("Error");
        return false;
    }
}

现在,您不需要使用异常,阅读它仍然是不错的选择。不管怎样,你还是得打个电话。异常花费大约4000-8000个时钟周期

bool Enable()
{
    if (GetStatus(ref status)) 
    { 
        // do stuff
        if (GetStatus(ref status)) 
        { 
            // do stuff
            if (GetStatus(ref status)) 
            { 
                // do stuff
                return true;
            }
        }
    }

    Trace.WriteLine("Error"); 
    return false;
}

使用LINQ,您可以执行以下操作:

delegate bool StatusFunc( ref int status );

bool Enable()
{
    var funcs = new StatusFunc[] 
    {
        GetStatusA,
        GetStatusB,
        GetStatusC
    };
    return funcs.All( f => f( ref status ) );
}

注意,这有点像黑客,因为
GetStatus
函数有副作用(修改状态),这在LINQ查询中是不允许的

这个怎么样?它需要对现有代码进行最小的更改<代码>收益回报是你的朋友;让编译器完成所有的脏活:

IEnumerable<bool> StatusChecks()
{
    // Do stuff
    yield return GetStatus( ref status );
    // Do stuff
    yield return GetStatus( ref status );
    // Do stuff
    yield return GetStatus( ref status );
}

bool Enable()
{
    foreach ( var b in StatusChecks() )
    {
        if ( !b )
        {   
            Trace.WriteLine("Error");                       
            return false;
        } 
    }
    return true;
}

真正的代码是同一行的6倍?我希望这不是真正的代码。它调用同一个方法9次有什么原因吗?实际代码执行许多方法,这些方法都依赖于前一个方法。这些方法中的每一个都会更新状态。正在执行的方法不是我的代码。@stijn为什么要使用
ref status
?不是我的选择,我正在使用的SDK就是这样工作的。我必须调用一个方法,获取状态,根据新的状态,我可以调用下一个方法或者停止Enable()函数。我认为@Stijn每次都在调用GetStatus(),因为状态可能已经改变,所以他希望尽快退出Enable()方法possible@Axarydax是的,我也这么想。这就是为什么我建议从那些方法返回值,作为调用该方法的结果来指示状态,而不仅仅是重复地点击
GetStatus()
方法(特别是因为它有一个
ref
参数来指示状态…)“do stuff”一点也不重要。它调用一个SDK方法(该方法反过来调用非托管代码),而SDK不在我的控制范围内。另请看我对这个问题的评论。@Stijn-Ahh好的。在这种情况下,我会同意弗雷德里克的建议,用一个大的try catch来包装这个东西,将
GetStatus()
更改为
ValidateStatus()
,如果继续下去不安全,就让它抛出一个异常。@Stijn说得清楚,如果你控制着代码,并且有很多实际的代码来代替这些注释,我会把我的建议和Frédéric的结合起来。这看起来像是一个选项,我会尝试一下。委托,委托列表,迭代——而不是简单的方法。这很酷,但要复杂得多。他们说我总是把东西搞得太复杂:)格利
bool Enable()
{
    if (GetStatus(ref status)) 
    { 
        // do stuff
        if (GetStatus(ref status)) 
        { 
            // do stuff
            if (GetStatus(ref status)) 
            { 
                // do stuff
                return true;
            }
        }
    }

    Trace.WriteLine("Error"); 
    return false;
}
delegate bool StatusFunc( ref int status );

bool Enable()
{
    var funcs = new StatusFunc[] 
    {
        GetStatusA,
        GetStatusB,
        GetStatusC
    };
    return funcs.All( f => f( ref status ) );
}
IEnumerable<bool> StatusChecks()
{
    // Do stuff
    yield return GetStatus( ref status );
    // Do stuff
    yield return GetStatus( ref status );
    // Do stuff
    yield return GetStatus( ref status );
}

bool Enable()
{
    foreach ( var b in StatusChecks() )
    {
        if ( !b )
        {   
            Trace.WriteLine("Error");                       
            return false;
        } 
    }
    return true;
}
bool Enable()
{
     var result = StatusChecks().All( b => b );
     if ( !result )
     {
         Trace.WriteLine("Error");                       
     }
     return result;
}