4

I have a list which contains three items. First element is integer, second one is also an integer and third one is another list. By using for each loop I'm able to print these items.

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

mainList.Add(binRead.ReadInt32()); // Reads first integer ant adds to mainList
mainList.Add(binRead.ReadInt32()); // Reads second integer ant adds to mainList

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

for(int i=0; i<n; i++)
{
  // Reads some data and adds it to avlDataList
}

mainList.Add(avlDataList); // Adds that list to mainList

foreach(var i in mainList)
{
   Console.WriteLine(i); // Prints items      
}

I get this output:

8
1
System.Collections.Generic.List`1[System.Object]

How can I modify my code to see what's inside of that list instead of getting this message? That avlDataList list has 10 elements. So i would like to see 12 elements in total.

Valdas S
  • 445
  • 1
  • 9
  • 20
  • Do you really need to use `object` here? Perhaps `string` or `int` would be more appropriate? – DavidG Nov 21 '17 at 11:38
  • It contains different type of data so I'm forced to use object – Valdas S Nov 21 '17 at 11:38
  • 2
    If that's the case, then I would suggest that your logic is likely seriously flawed. – DavidG Nov 21 '17 at 11:40
  • Yeah, it is, because it is my first time creating big program in c#. I only show small fragment of my project. However I believe there is somekind of solution here – Valdas S Nov 21 '17 at 11:41
  • 1
    use `mainList.AddRange(avlDataList);` - instead of adding the list object this will add the list elements – Patrick Artner Nov 21 '17 at 11:47
  • What it will do? – Valdas S Nov 21 '17 at 11:48
  • I guess you actually want to flatten this inner list: `mainList.AddRange(avlDataList);`. Also change from `List` to `List`. It's rarely needed to be able to store anything in a list. That's often a code smell. – Tim Schmelter Nov 21 '17 at 11:48
  • @Cal Lazy much? see [List.AddRange](https://msdn.microsoft.com/en-us/library/z883w3dc(v=vs.110).aspx) – Patrick Artner Nov 21 '17 at 11:49
  • Your problem is that the `ToList` implementation on `List` is the default which is to print out the type of the object. There is no magic to make it display a list of the contents so if you want to do that you'll need to write the code yourself (basically repeat what you did for the outer list but for the inner list). – Chris Nov 21 '17 at 11:50
  • Duplicate of [Why am I getting System.Collections.Generic.List\`1\[System.String\] instead of the list's contents?](https://stackoverflow.com/questions/16106181/why-am-i-getting-system-collections-generic-list1system-string-instead-of-the) – TylerH Sep 10 '20 at 21:16

3 Answers3

2

Try use code below:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        List<object> mainList = new List<object>();

        mainList.Add(1); 
        mainList.Add(2); 

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

        for (int i = 0; i < 10; i++)           
            avlDataList.Add(100 + i);  

        mainList.Add(avlDataList); 

        foreach (var i in mainList)
        {
            if (i.GetType() != avlDataList.GetType())
                Console.WriteLine(i);  

            if (i.GetType() == avlDataList.GetType())                
                foreach (var ii in avlDataList)
                    Console.WriteLine(ii); 
        }
    }
}

output: 1 2 100 101 102 103 104 105 106 107 108 109

MKasprzyk
  • 503
  • 5
  • 17
2

As per MKasprzyk's answer, you can check the type of each object when iterating through the main list to decide how to output it to the console. Otherwise the default ToString() method will be called (see below).

If you are using C# 7, you can (arguably) increase readability by using switch pattern matching and simply write:

foreach (var i in mainList)
{
    switch (i)
    {
        case IEnumerable<object> li:
            Console.WriteLine($"List: {string.Join(", ", li)}");
            break;
        default:
            Console.WriteLine(i);
            break;
    }
}

This way, non-enumerable objects are output as at present, whereas objects that implement the IEnumerable<object> interface, such as a List<object> are output on a single line, comma separated, with each list value output using the object's ToString() method, e.g.:

23

45

List: 12, 54, 69, ...

Why are List values appearing like this?

System.Collections.Generic.List`1[System.Object]

Looking at the documentation for the List<T> class, the ToString() method is derived directly from the base Object class, where it simply outputs the Type name. There is no specific override for this class to make it do something special.

You could define your own generic class derived from List<T> that overrides the ToString() operator to show items in a particular way if you desired, rather than having special cases in your console output code:

public class ConsoleFriendlyList<T> : List<T>
{
    public override string ToString()
    {
        return $"List: {string.Join(", ", this)}";
    }
}

Now if you modified your code to define avlDataList as follows, it would output the same as above:

var avlDataList = new ConsoleFriendlyList<object>();
Community
  • 1
  • 1
wardies
  • 1,149
  • 10
  • 14
0

If your first two items in mainList really are fixed then change this

foreach(var i in mainList)
{
   Console.WriteLine(i); // Prints items      
}

to

Console.WriteLine(mainList.Item[0]);
Console.WriteLine(mainList.Item[1]);

foreach(var i in mainList.Item[2])
{
   Console.WriteLine(i); // Prints items      
}

Looks pretty ugly to me, though.

spodger
  • 1,668
  • 1
  • 12
  • 16