为局部变量定义动态计算公式

define a dynamically-evaluated formula for a local variable

我正在查看一段错误处理代码,如下所示:

if (condition) {
    thereIsAProblem = true;
    problemDescription = "x";
}

if (!thereIsAProblem && condition2) {
    thereIsAProblem = true;
    problemDescription = "y";
}

我想知道是否有一种方法可以定义一个名为 thereIsNotAProblem 的局部变量,该变量动态地基于 thereIsAProblem 的值。换句话说:

var thereIsAProblem = false;
var thereIsNotAProblem = *** some expression... ***

Console.WriteLine(thereIsNotAProblem);   // true
thereIsAProblem = true;
Console.WriteLine(thereIsNotAProblem);   // false

if (thereIsNotAProblem && condition3) {
  ..
}

是否可以在上面的行中输入一些表达式,将 thereIsNotAProblem 的值指定为基于 !thereIsAProblem 的动态公式,并且仍然允许 thereIsNotAProblem在任何需要 bool 值的地方提供?

不太...但您可以改为将其设为委托:

Func<bool> thereIsNotAProblem = () => { /* some expression */ };

Console.WriteLine(thereIsNotAProblem());   // true
thereIsAProblem = true;
Console.WriteLine(thereIsNotAProblem());   // false

请注意现在每次我们想要评估 thereIsNotAProblem 我们调用委托...它评估表达式以获得 bool 值。

虽然您可以通过声明 lambda 来做到这一点,

var thereIsAProblem = false;
Func<bool> thereIsNotAProblem = () => !thereIsAProblem;

我认为你不应该这样做。 thereIsAProblemthereIsNotAProblem 看起来非常相似,因此很容易将一个误读为另一个。使用 ! 来否定具有正名称的变量是很好理解和易于阅读的,应该会导致更少的错误。

我进一步认为,更好的解决方案是 "fail fast" 出现问题后立即返回的方法,避免了首先测试早期问题的需要:

if (condition) 
{
    problemDescription = "x";
    return;
}

if (condition2) 
{
    problemDescription = "y";
    return;
}
...

您可以使用以下方法 (另见 .NET Fiddle https://dotnetfiddle.net/E9X6XJ

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("YourQuestion() returns " + YourQuestion());
        Console.WriteLine("AnswerOne() returns " + AnswerOne());
        Console.WriteLine("AnswerTwo() returns " + AnswerTwo());
    }

    private static bool condition1()
    {
        return false;
    }

    private static bool condition2()
    {
        return true;
    }

    private static bool condition3()
    {
        return true;
    }


    public static string YourQuestion() 
    {
        var thereIsAProblem = false;
        var problemDescription = "";        

        if (condition1()) {
            thereIsAProblem = true;
            problemDescription = "x";
        }

        if (!thereIsAProblem && condition2()) {
            thereIsAProblem = true;
            problemDescription = "y";
        }

        return problemDescription;
    }

    public static string AnswerOne() 
    {
        return checkCondition1() ??
               checkCondition2() ??
               checkCondition3();
    }   

    private static string checkCondition1()
    {       
        return condition1() ? "x" : null;       
    }

    private static string checkCondition2()
    {       
        return condition2() ? "y" : null;
    }

    private static string checkCondition3()
    {       
        return condition3() ? "z" : null;           
    }


    public static string AnswerTwo()
    {       
        var conditionChecks = new Dictionary<string,Func<bool>>();
        conditionChecks.Add("x",condition1);
        conditionChecks.Add("y",condition2);
        conditionChecks.Add("z",condition3);
        foreach (var check in conditionChecks)
        {           
            if (check.Value())
            {
                return check.Key;
            }
        }
        return null;
    }

}