简化长嵌套if语句工作流C#
此程序用于验证Excel行数据。 如果If语句为false,则需要将消息附加到字符串中,以此类推,以获得N个If语句。这不起作用,因为正如您所看到的,如果第一个if语句失败,我不会继续处理其他if语句。稍后,我还需要处理100多个列,所以我正在寻找一种方法来实现这一点 有没有其他方法可以重写它,使它更具可读性,更少重复?我知道我可以做一个巨大的if(…&&…)来验证所有单元格和单个if语句以附加消息,但我想知道是否还有其他方法可以做到这一点。我想保留错误的顺序,但这并不重要。结果类似于简化长嵌套if语句工作流C#,c#,if-statement,C#,If Statement,此程序用于验证Excel行数据。 如果If语句为false,则需要将消息附加到字符串中,以此类推,以获得N个If语句。这不起作用,因为正如您所看到的,如果第一个if语句失败,我不会继续处理其他if语句。稍后,我还需要处理100多个列,所以我正在寻找一种方法来实现这一点 有没有其他方法可以重写它,使它更具可读性,更少重复?我知道我可以做一个巨大的if(…&&…)来验证所有单元格和单个if语句以附加消息,但我想知道是否还有其他方法可以做到这一点。我想保留错误的顺序,但这并不重要。结果类似于“faci
“facilityID无效,daysOfTheWeek无效”
我还返回了一个自定义对数据类型
string facilityID, facilityDockDoorID, increment, hoursOfOperationId, updatedById, startTime, endTime, dockDoorServiceType, daysOfTheWeek;
facilityID = row[0];
facilityDockDoorID = row[1];
increment = row[2];
hoursOfOperationId = row[3];
updatedById = row[4];
startTime = row[5];
endTime = row[6];
dockDoorServiceType = row[7];
daysOfTheWeek = row[8];
string errorMessage = " is invalid";
if (IsInt(facilityID))
{
if (IsInt(facilityDockDoorID))
{
if (IsInt(increment))
{
if (IsInt(hoursOfOperationId))
{
if (IsInt(updatedById))
{
if (IsTime(startTime))
{
if (IsTime(endTime))
{
if (IsValidDockDoorServiceType(dockDoorServiceType))
{
if (IsValidDayOfTheWeek(daysOfTheWeek))
{
isDataValid.First = true;
}
else
{
isDataValid.Second += "daysOfTheWeek" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "dockDoorServiceType" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "endTime" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "startTime" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "updatedById" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "hoursOfOperationId" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "increment" + errorMessage + ",";
}
}
else
{
isDataValid.Second += "facilityDockDoorID" + errorMessage + ",";
}
}
else
{
isDataValid.Second = "facilityID" + errorMessage + ",";
}
return isDataValid;
}
您可以反转if语句。例如:
if(!IsInt(facilityID))
{
isDataValid.Second = "facilityID" + errorMessage + ",";
}
if(!IsInt(facilityDockDoorID))
{
isDataValid.Second += "facilityDockDoorID" + errorMessage + ",";
}
如果反转
If
语句并返回到每个语句中,您可以像这样将代码展平
if (!IsInt(facilityID))
{
isDataValid.Second = "facilityID" + errorMessage + ",";
return isDataValid;
}
if (!IsInt(facilityDockDoorID))
{
isDataValid.Second += "facilityDockDoorID" + errorMessage + ",";
return isDataValid;
}
if (!IsInt(increment))
{
isDataValid.Second += "increment" + errorMessage + ",";
return isDataValid;
}
if (!IsInt(hoursOfOperationId))
{
isDataValid.Second += "hoursOfOperationId" + errorMessage + ",";
return isDataValid;
}
if (!IsInt(updatedById))
{
isDataValid.Second += "updatedById" + errorMessage + ",";
return isDataValid;
}
if (!IsTime(startTime))
{
isDataValid.Second += "startTime" + errorMessage + ",";
return isDataValid;
}
if (!IsTime(endTime))
{
isDataValid.Second += "endTime" + errorMessage + ",";
return isDataValid;
}
if (!IsValidDockDoorServiceType(dockDoorServiceType))
{
isDataValid.Second += "dockDoorServiceType" + errorMessage + ",";
return isDataValid;
}
if (IsValidDayOfTheWeek(daysOfTheWeek))
{
isDataValid.First = true;
}
else
{
isDataValid.Second += "daysOfTheWeek" + errorMessage + ",";
}
return isDataValid;
然而,基于您连接到秒的事实,更可能的情况是您实际上想要
if (!IsInt(facilityID))
isDataValid.Second = "facilityID" + errorMessage + ",";
if (!IsInt(facilityDockDoorID))
isDataValid.Second += "facilityDockDoorID" + errorMessage + ",";
if (!IsInt(increment))
isDataValid.Second += "increment" + errorMessage + ",";
if (!IsInt(hoursOfOperationId))
isDataValid.Second += "hoursOfOperationId" + errorMessage + ",";
if (!IsInt(updatedById))
isDataValid.Second += "updatedById" + errorMessage + ",";
if (!IsTime(startTime))
isDataValid.Second += "startTime" + errorMessage + ",";
if (!IsTime(endTime))
isDataValid.Second += "endTime" + errorMessage + ",";
if (!IsValidDockDoorServiceType(dockDoorServiceType))
isDataValid.Second += "dockDoorServiceType" + errorMessage + ",";
if (!IsValidDayOfTheWeek(daysOfTheWeek))
isDataValid.Second += "daysOfTheWeek" + errorMessage + ",";
isDataValid.First = isDataValid.Second.Length == 0;
return isDataValid;
请注意,我正在比较秒的长度
,以确定是否发生了任何错误。您可以构建验证程序函数的集合,例如:
List<Func<string[], StringBuilder, bool>> validators = new List<Func<string[], StringBuilder, bool>>();
validators.Add((row, logger) =>
{
string facilityID = row[0];
if(IsInt(facilityID))
{
logger.AppendLine("facilityID is invalid");
return false;
}
return true;
});
validators.Add((row, logger) =>
{
string increment = row[2];
if (IsInt(increment))
{
logger.AppendLine("increment is invalid");
return false;
}
return true;
});
. . .
通过这种方式,您可以将验证器逻辑分解为更小的块。这样可以避免嵌套if
语句。每个验证器负责挑选它想要验证的数据,返回有效/无效的bool
,并将所有消息记录到公共StringBuilder
。随着验证器列表的增加,您可以向集合中添加一个新函数。最好将模式与代码功能分开。
这允许您将来更改模式,而无需更改其余代码
public class SchemaItem
{
public int Index;
public string ColumnName;
public int ParsedValue;
public SchemaItem(int index, string columnName)
{
Index = index;
ColumnName = columnName;
}
}
public static Dictionary<int, SchemaItem> Schema = new Dictionary<int, SchemaItem>
{
{0, new SchemaItem(0, "facilityID")},
{1, new SchemaItem(1, "facilityDockDoorID")},
{2, new SchemaItem(2, "increment")},
{3, new SchemaItem(3, "hoursOfOperationId")},
{4, new SchemaItem(4, "updatedById")},
{5, new SchemaItem(5, "startTime")},
{6, new SchemaItem(6, "endTime")},
{7, new SchemaItem(7, "dockDoorServiceType")},
{8, new SchemaItem(8, "daysOfTheWeek")},
};
private static bool ParseIntAndOrWriteFailMessage(string[] row, StringBuilder logger, int index)
{
string cellContents = row[index];
string columnName = Schema[index].ColumnName;
int intContents = -1;
if (int.TryParse(cellContents, out intContents))
{
Schema[index].ParsedValue = intContents;
return true;
}
logger.AppendFormat("{0} is invalid,", columnName);
return false;
}
不要嵌套if
语句,按顺序进行。可能重复@nicholas我看了那个问题。但是,我不打算从任何if语句返回。只有通过所有检查后才打算回来。最重要的部分是获取消息,但是您发布的代码示例在第一次检查失败并返回后将短路。我知道您在说什么了。我想那是我的错误。我将把返回放在外面,我在复制粘贴我的代码时不小心把它放在了里面。OP还需要添加return
语句来获得相同的行为。这难道不意味着,我需要8个单独的if语句来进行追加。然后我还需要一个巨人if(…&&&…&&&&…)来检查是否所有数据都经过验证?顺便说一句,我返回的是一个自定义对结构,而不仅仅是一个boolean@ygongdev不。您可以检查错误消息中是否有文本,或者设置其他错误标志,稍后再检查。我想这是我最后的选择。我想知道我是否可以做一些类似于switch()的事情,但是对于顺序if语句。因为以后,这个方法需要100+列的100+if语句如果你做了很多这样的检查,你可能想要装配某种通用的“scheme”验证器函数,它通过列循环,并使用循环而不是硬编码函数与预期的数据类型进行比较。您可以将期望的类型放在逗号分隔的列表中,如“int,int,date,date,string”,将它们拆分,然后放到循环中的一个开关中。@BradleyUffner,是的,我将进行大量此类检查,这就是为什么我要寻找更合适的解决方案。我试试你的建议。同时,我将接受这个作为临时解决方案,因为它实现了我希望当前代码实现的功能。我喜欢这个实现,因为您可以更进一步。对于超级干净的代码,理想情况下您需要的是以这样一种方式定义您的模式,即只需对该代码进行最少的更新即可对其进行更改或修改。
public class SchemaItem
{
public int Index;
public string ColumnName;
public int ParsedValue;
public SchemaItem(int index, string columnName)
{
Index = index;
ColumnName = columnName;
}
}
public static Dictionary<int, SchemaItem> Schema = new Dictionary<int, SchemaItem>
{
{0, new SchemaItem(0, "facilityID")},
{1, new SchemaItem(1, "facilityDockDoorID")},
{2, new SchemaItem(2, "increment")},
{3, new SchemaItem(3, "hoursOfOperationId")},
{4, new SchemaItem(4, "updatedById")},
{5, new SchemaItem(5, "startTime")},
{6, new SchemaItem(6, "endTime")},
{7, new SchemaItem(7, "dockDoorServiceType")},
{8, new SchemaItem(8, "daysOfTheWeek")},
};
private static bool ParseIntAndOrWriteFailMessage(string[] row, StringBuilder logger, int index)
{
string cellContents = row[index];
string columnName = Schema[index].ColumnName;
int intContents = -1;
if (int.TryParse(cellContents, out intContents))
{
Schema[index].ParsedValue = intContents;
return true;
}
logger.AppendFormat("{0} is invalid,", columnName);
return false;
}
StringBuilder logger = new StringBuilder();
foreach (var column in Schema.Select(pair => pair))
{
ParseIntAndOrWriteFailMessage(row, logger, column.Key);
}
// Parsed values are now stored in the Schema Dictionary (which probably could use a better name)