【问题标题】:How do you iterate through a mixed List<t> and print contents to console in C#?如何在 C# 中遍历混合 List<t> 并将内容打印到控制台?
【发布时间】:2017-06-07 19:58:49
【问题描述】:

我有一个List&lt;object&gt;,其中包含字符串甚至其他列表。

List<object> NewArray = new List<object>();

所以基本上这个列表包含一个混合物......

作为健全性检查,我想将内容打印到控制台。我首先遍历并测试该元素是否为列表。如果不是,那么它将是一个字符串,可以打印到控制台。如果它是一个列表,我想遍历并将字符串内容打印到控制台,但使用制表符来缩进它。

到目前为止我有这个:

    for (int outer = 0; outer < NewArray.Count; outer++)
            {

                var innerList = NewArray[outer];

                if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
                {

                    for (int inner = 0; inner < innerList.Count; inner++)
                    {

                        //print string
                    }
                }
                else
                {
                    //print string
                }
    }

我不想使用foreach 循环,因为我不确定列表的顺序是否得到保证,并且将来会添加一个增量编号(可以由内部和外部变量提供)。

我遇到的问题是这里的错误:

inner < innerList.Count

这是:

运算符“

我需要做些什么来克服这个问题?我不确定这是实现最终结果的最有效方式,但是....

【问题讨论】:

  • 不,不。检查它是否是非通用 IEnumerable,然后对其进行转换并对其进行 foreach。使其成为递归方法。完成。
  • 拥抱 OOP!您正在通过列出随机废话来与语言作斗争。为您保留在列表中的任何内容创建强类型。通过覆盖ToString() 方法或添加Display() 方法或与接口类似的方法,让这些类型自己处理打印。
  • 看起来 Count 可能是 IEnumerable.Count() 扩展方法。如果 innerList 是 Object,我不知道你是怎么做到的;我们能看到完整的代码吗?
  • @itsme86 "随机废话" +1

标签: c# list iteration


【解决方案1】:
static void Main()
{
    var randomCrap = new List<Object>
    {
        1, "two",
        new List<object> { 3, 4 },
        5, 6,
        new List<object> {
            new List<object> { 7, 8, "nine" },
        },
    };

    randomCrap.PrintAll();
}

输出:

1
two
3
4
5
6
7
8
nine

使用这个:

public static class Extensions
{
    public static void PrintAll(this Object root)
    {
        foreach (var x in root.SelectAll())
        {
            Console.WriteLine(x);
        }
    }

    public static IEnumerable<Object> SelectAll(this object o)
    {
        //  Thank you, eocron
        if (o is String)
        {
            yield return o;
        }
        else if (o is IEnumerable)
        {
            var e = o as IEnumerable;
            foreach (var child in e)
            {
                foreach (var child2 in child.SelectAll())
                    yield return child2;
            }
        }
        else
        {
            yield return o;
        }
    }
}

【讨论】:

  • @EdPlunkett 对此表示感谢,但编译此文件的唯一方法是将public static void PrintAll(Object root) 更改为public static void PrintAll(this Object root),然后我在此行的foreach 处获得An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll @ 987654328@
  • @cosmarchy 谢谢,我去看看。
  • @cosmarchy 好收获!我对递归感到困惑。现已修复。
【解决方案2】:

如果您知道您的对象是某个泛型类型的List&lt;&gt;,您总是可以转换为IList 并以这种方式循环它。

解释你的代码:

if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
    var list = (IList)innerList;
    for (int inner = 0; inner < list.Count; inner++)
    {
        Console.WriteLine(list[inner].ToString());
        //print string
    }
}

但实际上,您应该按照 itsme86 所说的去做,并使用重写的 ToString()Display() 方法创建强类型。

【讨论】:

    【解决方案3】:

    这里是做你想做的更简单的方式:

    public static void DeepPrint(object obj, int recursionLevel)
    {
        if(obj == null)
        {
            //print null
            return;
        }
        var str = obj as string;
        if(str != null)
        {
            //print str
            return;
        }
        var enumer = obj as IEnumerable;
        if(enumer != null)
        {
            foreach(var e in enumer)
            {
                DeepPrint(e, recursionLevel+1);
            }
            return;
        }
        //print obj.ToString();
    }
    

    然后在任何你想要的地方这样调用它:

    DeepPrint(myObjectOrList, 0);
    

    PS

    对于那些说“随机垃圾”的人 - 拥抱 string.Format(...),拥抱一般的序列化,拥抱 WCF 和动态等等。这个世界上有很多随机的东西,什么不真的需要强类型。事实上,如果你为一些常用函数提供强类型,它只会变成“废话”。

    【讨论】:

    • 你忘记了缩进,但递归也在我的脑海中
    • 您将 IEnumerable 视为 IEnumerator。该循环不会编译。
    • re:随机废话,同意 - 这是一个响亮的短语,但是当您想追踪 List&lt;T&gt; 时,“子类化它”不是答案。
    【解决方案4】:

    您可以这样做的一种方法是检查对象是否实现ICollection,如果是,则迭代内容。我创建了一个递归方法来处理集合包含其他集合的情况,其中包含一个 indentAmount 参数,以便嵌套集合每次遇到时都会缩进一个制表符:

    public static void PrintItem(object item, int indentAmount = 0)
    {
        var indent = new string('\t', indentAmount);
        if (item == null) Console.WriteLine($"{indent}<null>");
    
        if (item is ICollection)
        {
            var innerItems = item as IEnumerable;
            Console.WriteLine($"{indent}Collection type encountered:");
            indentAmount++;
            foreach (var innerItem in innerItems)
            {
                PrintItem(innerItem, indentAmount);
            }
        }
        else
        {
            Console.WriteLine($"{indent}{item}");
        }
    }
    

    用法

    private static void Main()
    {
        var items = new List<object>
        {
            "first",
            2,
            new List<string> {"listFirst", "listSecond"},
            new[] {"arrayFirst", "arraySecond"},
            new ArrayList {"arrayListFirst", "arrayListSecond"},
            "third",
            new List<List<string>>
            {
                new List<string> {"nestedList1First", "nestedList1Second"},
                new List<string> {"nestedList2First", "nestedList2Second"}
            },
            4f,
            new object[] {5d, "six", new List<object>{"seven", 8} },
            9,
            "ten"
        };
    
        PrintItem(items);
    
        Console.WriteLine("\nDone!\nPress any key to exit...");
        Console.ReadKey();
    }
    

    输出

    【讨论】:

      猜你喜欢
      • 2014-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2011-08-06
      • 2015-03-16
      • 1970-01-01
      相关资源
      最近更新 更多