Header

The method SelectMany of Enumerable data types in C# can be confusing if you try and use it on string fields in objects.

Here is a typical example on this method's usage:


		class TestType1 {
			public string Name { get; set; }
			public List<string> Values { get; set; }
		}
		

		var foo = new List<TestType1> {
			new TestType1 { Name = "Car", Value = new List<string> { "Mercedes", "Audi", "Volkswagen", "Tesla" } },
			new TestType1 { Name = "Motorcycle", Value = new List<string> { "Suzuki", "Kawasaki", "BMW" } },
			new TestType1 { Name = "Fighterplane", Value = new List<string> { "Mig-29", "F16", "F22", "Gripen" } }
		};

		var valList = foo.SelectMany( c => c.Value );

		foreach(var value in valList ) {
			Console.WriteLine(value);
		}
		

		Mercedes
		Audi
		Volkswagen
		Tesla
		Suzuki
		Kawasaki
		BMW
		Mig-29
		F16
		F22
		Gripen
		

As you can see, this lists out all the values in the Values lists.

However, say that you have a list of objects with string fields, and you want to get the value of those fields. Take the following example:


		class TestType2 {
			public string Name { get; set; }
			public string Value { get; set; }
		}

		var foo = new List<TestType2> {
			new TestType2 { Name = "Car", Value = "Audi" },
			new TestType2 { Name = "Motorcycle", Value = "Kawasaki" },
			new TestType2 { Name = "Fighterplane", Value = "F22" }
		};

		var bar = foo.SelectMany( c => c.Value );

		foreach(var value in bar) {
			Console.WriteLine(value);
		}
		

Now you might expect that you'll get a list similar to the one in the first example, but what you'll get instead is this:


		T
		e
		s
		l
		a
		K
		a
		w
		a
		s
		a
		k
		i
		F
		2
		2
		

What you see here is due to the fact SelectMany selects items from lists, and since strings are considerd arrays of characters, you get each item in those arrays listed.

What you need to do instead, to get the expected result, is this:


		var x = foo.Select( c => c.Name );
		foreach(var y in x) {
			Console.WriteLine(y);
		}
		

Which yields the expected output:


		Audi
		Kawasaki
		F22