是否可能有一个函数作为while条件

本文关键字:作为 while 条件 bool 有一个 函数 是否 | 更新日期: 2023-09-27 18:18:00

晚上好

我想知道我是否可以这样做:

while(true)
{
   MyEnum currentValue = GetMyEnumValueFromDB();
   if(currentValue == MyEnum.BreakIfYouGetThis)
      break;
   else if(currentValue == MyEnum.AlsoBreakIfYouGetThis)
      break;
   else
      //Do some computing
}

但是不使用while(true)循环,我想将条件逻辑封装在Func中并像这样执行:

while(new Func<bool>(/* what goes here? */))
{
   //Do some computing
}

至少在我的情况下,它会看起来更干净,但我不确定如何做到这一点(有点新在Func/Action..)。

EDIT希望这能澄清:
也可以这样做:

while(GetMyEnumValueFromDB() != MyEnum.BreakIfYouGetThis && 
      GetMyEnumValueFromDB() != MyEnum.AlsoBreakIfYouGetThis)
{
   //Do some computing
}

但是这是对数据库的2个调用…

谢谢=)

是否可能有一个函数<bool>作为while条件

可以有:

Func<bool> condition = ...;
while (condition())
{
}

你在想这个吗?我不太清楚……

编辑:在你给出的例子中,我会使用这样的内容:
private static readonly MyEnum[] BreakEnumValues = { 
    MyEnum.BreakIfYouGetThis,
    MyEnum.AlsoBreakIfYouGetThis
};
...
while (!BreakEnumValues.Contains(GetMyEnumValueFromDB()))
{
    ...
}

或:

private static bool ShouldBreak(MyEnum enumFromDatabase)
{
    return enumFromDatabase == MyEnum.BreakIfYouGetThis ||
           enumFromDatabase == MyEnum.AlsoBreakIfYouGetThis;
}
...
while (!ShouldBreak(GetMyEnumValueFromDB))
{
    ...
}

编辑:为了反驳keith的回答,这是完全有效的:

while (new Func<bool>(() => {
    Console.WriteLine("Evaluating...");
    return true;
})()) {
    Console.WriteLine("In loop");
    count++;
    if (count == 5)
    {
        break;
    }
}

这是可怕的,但它是有效的。(通过显式地调用Invoke,可以使它稍微不那么可怕,但它仍然不太好。)

您可以这样做,但如果您没有令人信服的理由这样做(例如您将条件函数作为参数传递),我将直接将您的逻辑包装在函数中并直接调用它:

while(KeepGoing())
{
    //Do stuff
}
bool KeepGoing()
{
    // Check conditions for continuing
    var value = GetMyEnumValueFromDB();
    return value != MyEnum.BreakIfYouGetThis && value != MyEnum.AlsoBreakIfYouGetThis;
}

首先,在while循环中调用数据库是一个坏主意。提前查询需要的内容并相应地循环。

似乎多态性可以在这里成为您的朋友。如果您需要保持相同的流,您可以这样做:

interface IWhileLoopContinuable
{
   bool KeepGoing {get;}
   void DoWork();
}

那么你可以在这个可枚举对象上使用TakeWhile:

foreach(var item in queriedAsIWhileLoopContinuable.TakeWhile(c => c.KeepGoing))
{
   item.DoWork();
}

话虽如此,您可以查询您想要的内容并进行处理

首先你不能"new"一个Func,就像你不能新建任何委托类型一样。你必须指定一个现有的命名方法或函数文字(又名匿名委托,lambda等)来初始化Func变量。

//these won't compile; Func has no constructor
Func<bool> condition = new Func<bool>();
//As Jon Skeet notes, these will compile because of language-provided syntax,
//even though Funcs have no constructor with a delegate parameter.
Func<bool> condition = new Func<bool>(SomeNamedMethodReturnsBool);
Func<bool> condition = new Func<bool>(()=>true);
//and these will compile because you're directly assigning the delegate
Func<bool> condition = SomeNamedMethodReturnsBool;
Func<bool> condition = ()=>true;

你实际上不能在c#中做你想做的事;匿名委托必须分配给变量或参数才能使用。它不能作为抽象意义上的"函数字面量"就地使用。

即使可以,我也不知道这种语句的用途。委托不会每次都重新实例化(编译器将匿名委托转换为包含类的命名私有函数,并使用mashup名称),但是您在调用堆栈上添加了一个层,只是为了计算可以直接放在while()语句括号中的常量表达式。匿名委托的主要用途是你可以在运行时交换lambdas,为了做到这一点,你必须有一个变量。