SelectMany не может быть выведен из использования

Я получаю следующую ошибку при попытке скомпилировать свой код:

Аргументы типа для метода "System.Linq.Enumerable.SelectMany(System.Collections.Generic.IEnumerable, System.Func > )" не может быть выведено из использования. Попробуйте указать аргументы типа в явном виде.

        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();

Я не понимаю, как я могу "напечатать" это еще дальше...

Ответ 1

Проблема в том, что внутренний SelectMany там не применим, и вы, вероятно, имели в виду Select.

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

Каждый entry будет отображаться в IEnumerable<RowArgumentVal> в соответствии с arguments.

Представьте, что внешний SelectMany был простым Select, и он генерировал бы List<IEnumerable<RowArgumentVal>>. Но поскольку это SelectMany, он "сгладит" результат в простой List<RowArgumentVal>.

Метод SelectMany ожидает сопоставления с IEnumerable<T> - not T. Ваш исходный код будет действителен, если только RowArgumentVal реализовал интерфейс IEnumerable<T>, который, я полагаю, не тот.

Ответ 2

Это кажется декартовым продуктом из обоих списков, поскольку между ними нет никакой связи. Вы можете присоединиться к ним, но это не совсем понятно, как это сделать.

Вот более читаемый и компилирующий способ создания декартова продукта:

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();

Ответ 3

Если вы хотите, чтобы декартовой продукт попытался сделать следующее

 var argumentsVal = from e in entries
    from a in arguments
    select new RowArgumentVal(...)

Ответ 4

В стороне, "дальнейшая набрав", которую вы могли бы сделать, было бы дать аргументы типа вызовам общего метода. В частности, если вы изменили второй SelectMany на SelectMany<RowArgument, RowArgumentVal>, у вас были бы ошибки

Невозможно неявно преобразовать тип RowArgumentVal в System.Collections.Generic.IEnumerable<RowArgumentVal>. Явное преобразование существует (вы пропускаете листинг?)

Невозможно преобразовать лямбда-выражение для делегирования типа System.Func<RowArgument,int,System.Collections.Generic.IEnumerable<RowArgumentVal>>, потому что некоторые возвращаемые типы в блоке неявно конвертируются в тип возвращаемого делегата

который, возможно, привел бы вас к другим ответам здесь, - что вы пытались вызвать метод, ожидающий последовательности, но вы давали ему один объект.

(Или, пытаясь решить, какие аргументы типа добавить, вы бы поняли, что было раньше.)