What is the return type for a generic list returning an anonymous 2-string type?

I have this function:

public static List<string> JoinDataTablesMultipleColumns(DataTable dt1, DataTable dt2, string col1, string col2, string col3) {
 var multiJoin = from table1 in dt1.AsEnumerable()
 join table2 in dt2.AsEnumerable()
 on new {
   Col1 = table1.Field < string > (col1),
   Col2 = table1.Field < string > (col2),
   Col3 = table1.Field < string > (col3),
 equals new {
   Col1 = table2.Field < string > (col1),
   Col2 = table2.Field < string > (col2),
   Col3 = table2.Field < string > (col3),
 select new {
   SeriesID = table1.Field < string > ("SeriesID"),
   CatID = table2.Field < string > ("CatID")

 //if ( multiJoin != null )
 //   return multiJoin.ToList();
 return null;

It works perfectly except that I have the wrong return type. The only way I can compile and run it is by returning null. When I stop the debugger before returning and examine multiJoin.ToList() in the watch window, it's exactly what I want:

enter image description here

But the return type is wrong. I keep trying List<string, string>, but that won't compile. Probably a simple thing but I am stuck. Any ideas?

2 answers

  • answered 2018-11-08 00:31 spender

    Instead of attempting returning an anonymous type (you can't declare an anonymous return type for your method), create a named type to hold your data:

    public class Item
        public string SeriesID { get; set;}

    and use it instead of the anonymous type that you are currently selecting at the end of your query.

    ...select new Item {
       SeriesID = table1.Field < string > ("SeriesID"),
       CatID = table2.Field < string > ("CatID")

  • answered 2018-11-08 00:31 Eric Lippert

    As you note, you're getting a list of anonymous type. Anonymous types are not designed to cross out of the methods that create them. There are ways to make that work, but they are confusing, difficult and arcane.

    Do not attempt to do this with anonymous types. In C# 7, you can use a tuple type and return List<(string, string)>, and then do

    select (table1.Field<string>("SeriesID"), table2.Field<string>("CatID"))

    In other versions of C#, make a nominal pair type and create an instance of it in your select clause.