鉴于以下代码,是否有更好的方法来构建它?
foreach(Thing item in SomeRandomList)
{
bool firstCondition = CalculateBool(item, someValue);
bool secondCondition = CalculateBool(item, someOtherValue);
//General things are done...
if(firstCondition || secondCondition)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
}
此外,如果有更多条件,即3:
,该怎么办?foreach(Thing item in SomeRandomList)
{
bool firstCondition = CalculateBool(item, someValue);
bool secondCondition = CalculateBool(item, someOtherValue);
//imagine as many more as you want.
bool nthCondition = CalculateBool(item, lastOtherValue);
//General things are done...
if(firstCondition || secondCondition || nthCondition)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else if(secondCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
}
答案 0 :(得分:6)
是:多态性。
从公共基础派生Thing
(或定义所有Thing
实现的接口)
如果失败,请将条件测试代码移到Thing
上的方法中。
答案 1 :(得分:3)
如果您可以在特定事项之后执行半特定事项,则可以尝试:
bool anyTrue = true;
if (firstCondition)
{
// Specific things
}
else if (secondCondition)
{
// Specific things
}
else
{
// Specific things
anyTrue = false;
}
if (anyTrue)
{
// Semi-specific things
}
我不知道它是否一定更好,但它有所不同......
或者,我不是全神贯注于C#3.0和花哨的新LINQ东西,但如果它足够表达你可以尝试类似(伪代码):
bool[] conditions =
{
CalculateBool(item, someValue),
CalculateBool(item, someOtherValue),
...
};
if (conditions.AnyTrue)
{
switch (conditions.IndexOfFirstTrueItem)
{
case 0:
// Specific things
break;
case 1:
// Specific things
break;
default:
// Specific things
break;
}
}
答案 2 :(得分:2)
我使用一些LINQ来使用中间查询来帮助减少循环中的逻辑:
// Get condition in the query.
var query =
from item in SomeRandomList
let condition1 = CalculateBool(item, someValue1)
let condition2 = CalculateBool(item, someValue2)
...
let conditionN = CalculateBool(item, someValueN)
where
condition1 || condition2 || ... || conditionN
select new { Item = item,
Condition1 = condition1, Condition1 = condition2, ...
ConditionN = conditionN };
foreach(var item in query)
{
//semi-specific things are done...
if(firstCondition)
{
//specific things are done...
}
else
{
//specific things are done...
}
}
希望这会极大地减少循环中的代码量。
在我看来,虽然你有一系列的值被传递给了SomeRandomList中每个项目的CalculateBool。如果是这种情况,那么您可以轻松生成一个查询,该查询执行交叉连接并对其进行过滤:
// Get all valid items across all values.
var query =
from item in SomeRandomList
from value in someValues
where CalculateBool(item, value)
select { Item = item, Value = value };
// Iterate and process.
foreach (var item in query)
{
// Use item.Item and item.Value.
// Specifically, use item.Value to perform a lookup
// in a map somewhere to determine the course of action
// instead of a giant switch statement.
}
这样可行,因为您的条件表明您只为每个项目设置了一个值。
答案 3 :(得分:2)
我喜欢使用Predicate<T>
及其相关Action
字典的方法。我在这里回答了类似的问题:
Coming out of the habit of writing ifs/elseifs for every possible condition
为您的问题稍微修改一下:
Dictionary<Predicate<Something>, Action> mappings = {{...}}
bool shouldDoAnything = mappings.Keys.Aggregate(true, (accum, condition) =>
accum || condition);
if (shouldDoAnything)
{
//do semi-specific things
foreach(DictionaryEntry<Predicate<Something>, Action> mapping in mappings)
{
if (mapping.Key(input))
{
mapping.Value(); //do specific things
break;
}
}
}
答案 4 :(得分:0)
我可能无法正确回答问题,如果函数的返回类型为2
而非bool
结果,则我们只能得{4}}结果,除非它是{{3也可以返回null。
所以
n
会这样做。
关于管理大型bool result = CalculateBool(item, someValue);
if(result) {}
else {}
组合?一种方法是使用Nullable<bool>
语句,这可以提高可读性。
但无论如何,方法应始终具有最少的可能决策路径,这称为
如果发生这种情况,请将代码拆分为更合适的方法
答案 5 :(得分:0)
foreach(Thing item in SomeRandomList)
{
DoGeneralThings(); //pass in whatever your require to the method
if(FirstCondition(item, someValue))
{
DoThingsWhenAnyConditionIsTrue(); //pass in whatever your require to the method
DoSpecificThingsForFirstCondition(); //pass in whatever your require to the method
continue;
}
if(SecondCondition(item, someValue))
{
DoThingsWhenAnyConditionIsTrue(); //pass in whatever your require to the method
DoSpecificThingsForSecondCondition(); //pass in whatever your require to the method
continue;
}
}