C# 有没有一种方法可以重用具有不同端点参数的循环?

C# 有没有一种方法可以重用具有不同端点参数的循环?,c#,C#,请不要被代码墙吓倒!我的问题是:我是否可以以某种方式重用代码,并将我想要的任何参数放在//DoSomething的位置?我不想复制和粘贴相同的代码墙,我想减少重复性并使其更易于维护。我想知道这个问题,但我没有看到一个简单的解决办法,我也找不到一个 for (int i = 0; i < treeListViewDatabase.SelectedObjects.Count; i++) { if (treeListViewDatabase

请不要被代码墙吓倒!我的问题是:我是否可以以某种方式重用代码,并将我想要的任何参数放在//DoSomething的位置?我不想复制和粘贴相同的代码墙,我想减少重复性并使其更易于维护。我想知道这个问题,但我没有看到一个简单的解决办法,我也找不到一个

for (int i = 0; i < treeListViewDatabase.SelectedObjects.Count; i++)
            {
                if (treeListViewDatabase.SelectedObjects[i] is NodeValueWithNodes rootNode)
                {
                    for (int m = 0; m < rootNode.ChildTreeViewSets.Count; m++)
                    {
                        if (rootNode.ChildTreeViewSets[m] is NodeValueWithNodes childNodeWithNode)
                        {
                            for (int k = 0; k < childNodeWithNode.ChildTreeViewSets.Count; k++)
                            {
                                if (childNodeWithNode.ChildTreeViewSets[k] is NodeValueWithNodes secondChildNodeWithNode)
                                {
                                    for (int p = 0; p < secondChildNodeWithNode.ChildTreeViewSets.Count; p++)
                                    {
                                        if (secondChildNodeWithNode.ChildTreeViewSets[p] is NodeValueWithDevices thirdChildNodeWithDevices)
                                        {
                                            for (int r = 0; r < thirdChildNodeWithDevices.ChildDeviceSet.Count; r++)
                                            {
                                                if (dataRows.Contains(thirdChildNodeWithDevices.ChildDeviceSet[r]))
                                                {
                                                    dataRows.Remove(thirdChildNodeWithDevices.ChildDeviceSet[r]);
                                                }
                                                // DoSomething() 
                                            }
                                        }
                                    }
                                }
                                if (childNodeWithNode.ChildTreeViewSets[k] is NodeValueWithDevices secondChildNodeWithDevice)
                                {
                                    for (int r = 0; r < secondChildNodeWithDevice.ChildDeviceSet.Count; r++)
                                    {
                                        if (dataRows.Contains(secondChildNodeWithDevice.ChildDeviceSet[r]))
                                        {
                                            dataRows.Remove(secondChildNodeWithDevice.ChildDeviceSet[r]);
                                        }
                                        // DoSomething();
                                    }
                                }
                            }
                        }
                        if (rootNode.ChildTreeViewSets[m] is NodeValueWithDevices childNodeDevices)
                        {
                            for (int n = 0; n < childNodeDevices.ChildDeviceSet.Count; n++)
                            {
                                if (dataRows.Contains(childNodeDevices.ChildDeviceSet[n]))
                                {
                                    dataRows.Remove(childNodeDevices.ChildDeviceSet[n]);
                                }
                                // DoSomething();
                            }
                        }
                    }
                }
                if (treeListViewDatabase.SelectedObjects[i] is NodeValueWithDevices rootNodeWithDevices)
                {
                    for (int n = 0; n < rootNodeWithDevices.ChildDeviceSet.Count; n++)
                    {
                        if (dataRows.Contains(rootNodeWithDevices.ChildDeviceSet[n]))
                        {
                            dataRows.Remove(rootNodeWithDevices.ChildDeviceSet[n]);
                        }
                        // DoSomething();
                    }
                }
            }
            for (int i = 0; i < dataRows.Count; i++)
            {
                // DoSomething();
            }
for(int i=0;i
*编辑*

按照人们的建议,我已经完全更改了代码。代码的箭头式外观被一个简单的递归所取代。这个实现使我的问题不存在,因为我可以循环通过数据行执行必要的操作

private void TraverseTreeView(IList selectedObjects, List<DataRow> dataRows)
    {
        if (selectedObjects == null)
        {
            return;
        }
        foreach (var selectedObject in selectedObjects)
        {
            if (selectedObject is NodeValueWithNodes withNodes)
            {
                TraverseTreeView(withNodes.ChildTreeViewSets, dataRows);
            }
            if (selectedObject is NodeValueWithDevices withDevices)
            {
                TraverseTreeView(withDevices.ChildDeviceSet, dataRows);
            }
            if (selectedObject is DataRow dataRow && !dataRows.Contains(dataRow))
            {
                dataRows.Add(dataRow);
            }
        }
        
    }
private void TraverseTreeView(IList selectedObjects,List dataRows)
{
如果(SelectedObject==null)
{
回来
}
foreach(selectedObject中的变量selectedObject)
{
如果(selectedObject是NodeValueWithNodesWithNodes)
{
TraverseTreeView(withNodes.ChildTreeView、dataRows);
}
如果(selectedObject是nodeValue with devices with devices)
{
TraverseTreeView(withDevices.ChildDeviceSet,dataRows);
}
if(selectedObject为DataRow DataRow&!dataRows.Contains(DataRow))
{
添加(dataRow);
}
}
}
您可以使用。它可能看起来像这样:

public void TraverseTree(TreeListView root, Action<T> toDo)
{
   //big set of loops goes in here

   //DoSomething(); is replaced with:
   toDo(rootNodeWithDevices.ChildDeviceSet[n]);
}
Traverse(treeListViewDatabase, (node) => {
    //code for whatever you want to do goes in here
});
var items = treeListViewDatabase.SelectedObjects.
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithDevices).
    Select(o => o.ChildDeviceSet);

foreach(var item in items)
{
    if (dataRows.Contains(item))
        dataRows.Remove(item);
    //DoSomething();
}
var items = Traverse(treeListViewDatabase).
    Where(o => o is NodeValueWithDevices).
    Select(o => o.ChildDeviceSet);
foreach(var item in items)
{
    if (dataRows.Contains(item))
        dataRows.Remove(item);
    //DoSomething();
}
我还倾向于首先像这样重新编写循环的初始集合:

public void TraverseTree(TreeListView root, Action<T> toDo)
{
   //big set of loops goes in here

   //DoSomething(); is replaced with:
   toDo(rootNodeWithDevices.ChildDeviceSet[n]);
}
Traverse(treeListViewDatabase, (node) => {
    //code for whatever you want to do goes in here
});
var items = treeListViewDatabase.SelectedObjects.
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithNodes).
    Select(o => o.ChildTreeViewSets).
    Where(o => o is NodeValueWithDevices).
    Select(o => o.ChildDeviceSet);

foreach(var item in items)
{
    if (dataRows.Contains(item))
        dataRows.Remove(item);
    //DoSomething();
}
var items = Traverse(treeListViewDatabase).
    Where(o => o is NodeValueWithDevices).
    Select(o => o.ChildDeviceSet);
foreach(var item in items)
{
    if (dataRows.Contains(item))
        dataRows.Remove(item);
    //DoSomething();
}
如果必须这样做,我会添加一个
ToList()
调用,以避免在迭代时修改此序列

做了这么多之后,我将进一步研究如何构建一个递归方法,以避免如此多的重复。例如,我不确定您有哪个第三方TreeListView控件,但如果它是标准TreeView控件,我可能会这样做:

public IEnumerable<TreeNode> Traverse(TreeView source)
{
    // See Local Functions:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions
    IEnumerable<TreeNode> innerTraverse(TreeNodeCollection root)
    {
        foreach(var node in root)
        {
            yield return node;
            foreach(var node in innerTraverse(root))
            {
                yield return node;
            }
        }
    }

    return innerTraverse(source.nodes));
}
这并不完全相同-我们还没有考虑选择