c# - 如何简化多个嵌套的 foreach 循环?
问题描述
private DataTable GetAttributeTable()
{
DataTable cltAttributeTable = new DataTable("CLT_ATTRIBUTE");
DataColumnCollection iRefColumns = cltAttributeTable.Columns;
//BETHiddenColumn is defined for hiding certain columns at the UI
//And can be used for manipulating entities internally
iRefColumns.AddRange(new[]
{
new BETHiddenColumn { ColumnName = CLDConstants.CLTGUID, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = CLDConstants.CLTNAME, DataType = typeof(string), ReadOnly = true },
new BETHiddenColumn { ColumnName = CLDConstants.SHEETID, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = CLDConstants.SHEETNAME, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "OBJECT_TYPE", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "OBJECT_NAME", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "ATTRIBUTE_NAME", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "ATTRIBUTE_VALUE", DataType = typeof(string), ReadOnly = false }
});
return cltAttributeTable;
}
public override async Task<DataTable> GetDataAsync(ControlNetworkStructure controlNetwork)
{
DataTable cltAttributeTable = GetAttributeTable();
try
{
using (var automationService = ConsumedServiceProvider.Provider.AutomationService)
{
foreach (string userDefinedLogicTemplate in selectedCLT)
{
var controlLogicClt =
automationService.AutomationClt.GetControlLogicTemplate(userDefinedLogicTemplate);
foreach (ISheet sheet in await controlLogicClt.GetSheets())
{
foreach (IFunctionCode functionCode in await sheet.GetFunctionCodes())
{
foreach (IHarmonyAttribute functionCodeAttribute in functionCode.Attributes)
{
DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
row["OBJECT_TYPE"] = "FUNCTION CODE";
row["OBJECT_NAME"] = functionCode.Name;
row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
cltAttributeTable.Rows.Add(row);
}
}
foreach (IInputReference inputReference in await sheet.GetInputReferences())
{
foreach (IHarmonyAttribute functionCodeAttribute in inputReference.Attributes)
{
DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
row["OBJECT_TYPE"] = "IREF";
row["OBJECT_NAME"] = inputReference.Name;
row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
cltAttributeTable.Rows.Add(row);
}
}
foreach (IOutputReference outputReference in await sheet.GetOutputReferences())
{
foreach (IHarmonyAttribute functionCodeAttribute in outputReference.Attributes)
{
DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
row["OBJECT_TYPE"] = "OREF";
row["OBJECT_NAME"] = outputReference.Name;
row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
cltAttributeTable.Rows.Add(row);
}
}
foreach (IText text in await sheet.GetTexts())
{
foreach (IHarmonyAttribute functionCodeAttribute in text.Attributes)
{
DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
row["OBJECT_TYPE"] = "TEXT";
row["OBJECT_NAME"] = text.Name;
row["ATTRIBUTE_NAME"] = functionCodeAttribute.Type;
row["ATTRIBUTE_VALUE"] = functionCodeAttribute.Value;
cltAttributeTable.Rows.Add(row);
}
}
}
}
}
}
catch (Exception exception)
{
LogService.LogException(this, ServiceResources.CONTEXT_CLD_EDITOR, "CLT Attribute",
exception);
}
finally
{
// Accepting all the modification to the table before leaving this method call
cltAttributeTable.AcceptChanges();
}
return cltAttributeTable;
}
描述
我有一个内部有多个 foreach 循环的方法,当我是 C# 的初学者时,我很难理解它。另外我读到在程序中编写多个 foreach 循环不是一个好习惯。该方法返回一个数据表并绑定到一个 Datagrid。任何人都可以帮我简化它,使它变得更好的可读性和更直观吗?
解决方案
好的,这很仓促,但我认为这是一个好的开始。我没有时间测试它,所以它可能有一些错误。此外,还有很大的改进空间。
private DataTable GetAttributeTable()
{
DataTable cltAttributeTable = new DataTable("CLT_ATTRIBUTE");
DataColumnCollection iRefColumns = cltAttributeTable.Columns;
//BETHiddenColumn is defined for hiding certain columns at the UI
//And can be used for manipulating entities internally
iRefColumns.AddRange(new[]
{
new BETHiddenColumn { ColumnName = CLDConstants.CLTGUID, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = CLDConstants.CLTNAME, DataType = typeof(string), ReadOnly = true },
new BETHiddenColumn { ColumnName = CLDConstants.SHEETID, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = CLDConstants.SHEETNAME, DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "OBJECT_TYPE", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "OBJECT_NAME", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "ATTRIBUTE_NAME", DataType = typeof(string), ReadOnly = true },
new DataColumn { ColumnName = "ATTRIBUTE_VALUE", DataType = typeof(string), ReadOnly = false }
});
return cltAttributeTable;
}
public override async Task<DataTable> GetDataAsync(ControlNetworkStructure controlNetwork)
{
DataTable cltAttributeTable = new DataTable();
try
{
using (var automationService = ConsumedServiceProvider.Provider.AutomationService)
{
foreach (string userDefinedLogicTemplate in selectedCLT)
{
var controlLogicClt =
automationService.AutomationClt.GetControlLogicTemplate(userDefinedLogicTemplate);
cltAttributeTable = await LoopDeLoop(controlLogicClt);
}
}
}
catch (Exception exception)
{
LogService.LogException(this, ServiceResources.CONTEXT_CLD_EDITOR, "CLT Attribute",
exception);
}
finally
{
// Accepting all the modification to the table before leaving this method call
cltAttributeTable.AcceptChanges();
}
return cltAttributeTable;
}
//Main loop with loops adding rows
private async Task<DataTable> LoopDeLoop(dynamic controlLogicClt)
{
DataTable cltAttributeTable = GetAttributeTable();
foreach (ISheet sheet in await controlLogicClt.GetSheets())
{
foreach (IFunctionCode functionCode in await sheet.GetFunctionCodes())
{
cltAttributeTable = GetNewRows(cltAttributeTable, functionCode.Attributes, functionCode.Name, "FUNCTION CODE", controlLogicClt, sheet);
}
foreach (IInputReference inputReference in await sheet.GetInputReferences())
{
cltAttributeTable = GetNewRows(cltAttributeTable, inputReference.Attributes, inputReference.Name, "IREF", controlLogicClt, sheet);
}
foreach (IOutputReference outputReference in await sheet.GetOutputReferences())
{
cltAttributeTable = GetNewRows(cltAttributeTable, outputReference.Attributes, outputReference.Name, "OREF", controlLogicClt, sheet);
}
foreach (IText text in await sheet.GetTexts())
{
cltAttributeTable = GetNewRows(cltAttributeTable, text.Attributes, text.Name, "TEXT", controlLogicClt, sheet);
}
}
}
//Adds the new created rows to the DataTable
private DataTable GetNewRows(DataTable cltAttributeTable, List<IHarmonyAttribute> attributes, string name, string objectType, dynamic controlLogicClt, ISheet sheet)
{
foreach (IHarmonyAttribute attribute in attributes)
{
cltAttributeTable.Rows.Add(GetNewRow(sourceDataRow, attribute, name, objectType, controlLogicClt, sheet));
}
}
//Creates and populates the new row
private DateRow GetNewRow(IHarmonyAttribute attribute, string name, string objectType, dynamic controlLogicClt, ISheet sheet)
{
DataRow row = GetRow(cltAttributeTable, controlLogicClt, sheet);
row["OBJECT_TYPE"] = objectType;
row["OBJECT_NAME"] = name;
row["ATTRIBUTE_NAME"] = attribute.Type;
row["ATTRIBUTE_VALUE"] = attribute.Value;
return row;
}
所以我又做了三个方法:
LoopDeLoop
--> 这是为了从主要方法中取出大部分循环,从而使其更清晰。此外,它使sheets
循环更清晰。
'GetNewRows' --> 这是一个通用IHarmonyAttribute
循环,无需使用四个循环。
GetNewRow
--> 这只是填充一个新行,但现在您不必这样做四次。
希望这可以帮助
推荐阅读
- python - 禁止直接分配到相关集的反面
- c++ - 在 cpp 中生成 128 位泊松分布数
- makefile - 依赖列表中 OR 运算符的用途是什么?
- google-tag-manager - Google 跟踪代码管理器:将“所有自定义事件”与事件条件一起使用
- visual-studio-code - 即将推出的 Visual Studio 代码建议
- apache-flink - Flink SQL 单元测试:如何分配水印?
- r - 在正则表达式中仅提取模式的第二个实例
- r - 如何取消嵌套 tsibbles 的 listcolumn?
- python-3.x - Python RobotFileParser 挂起读取
- python - 绘制没有 Turtle 模块的海龟路径