Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SelectMany cannot be inferred from the usage [duplicate]

Tags:

c#

linq

I get the following error when I try to compile my code:

The type arguments for method 'System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

        List<RowEntry> entries = ...
        List<RowArgument> arguments = ...

        var argumentsVal = entries.SelectMany((RowEntry entry) =>
            (IEnumerable<RowArgumentVal>)arguments.SelectMany((RowArgument arg) => 
            new RowArgumentVal()
            {
                Action = "X" 
                , EntryID = entry.ID
                , ArgID = arg.ID
                , Val_BIT = true
                , Val_DATE = new DateTime(2014, 01, 04)
                , Val_DATETIME = new DateTime(2014, 01, 04)
                , Val_DECIMAL = 4.6M
                , Val_INT = 88
                , Val_TIME = new TimeSpan(6, 0, 0)
            }
        ).Cast<RowArgumentVal>()).Cast<RowArgumentVal>().ToList();

I don't get how I can "type" this even further...

like image 472
Serge Profafilecebook Avatar asked Aug 29 '14 08:08

Serge Profafilecebook


3 Answers

The problem is that the inner SelectMany isn't applicable there, and you probably meant Select.

var argumentsVal = entries.SelectMany(entry =>
    arguments.Select(arg => new RowArgumentVal())).ToList();

Each entry will be mapped into an IEnumerable<RowArgumentVal> according to the arguments.

Imagine the outer SelectMany was a simple Select, and it would generate List<IEnumerable<RowArgumentVal>>. But because it is SelectMany, it will "flatten" the result into a simple List<RowArgumentVal>.

The SelectMany method expects a mapping to IEnumerable<T> - not T. Your original code would be valid if RowArgumentVal just happened to implement the IEnumerable<T> interface, which I suppose isn't the case.

like image 139
SimpleVar Avatar answered Oct 13 '22 15:10

SimpleVar


That seems to be a cartesian product from both lists since there is no relation between them. You may want to join them but it's not exactly clear how.

Here is a more readable and compiling way to produce a cartesian product:

var query = from entry in entries
            from argument in arguments
            select new RowArgumentVal
            {
               Action = "X", EntryID = entry.ID,  ArgID = argument.ID, // ...
            };

List<RowArgumentVal> argumentsVal = query.ToList();
like image 34
Tim Schmelter Avatar answered Oct 13 '22 16:10

Tim Schmelter


If you want a cartesian product try doing the following

 var argumentsVal = from e in entries
    from a in arguments
    select new RowArgumentVal(...)
like image 36
Sebastian Piu Avatar answered Oct 13 '22 15:10

Sebastian Piu