Присвоение свойства анонимного типа с помощью анонимного метода

Я новичок в функциональной стороне С#, извините, если вопрос хромой.

Учитывая следующий код WRONG:

var jobSummaries = from job in jobs
                   where ...
                   select new 
                   {
                        ID = job.ID,
                        Description = job.Description,
                        FileName = (job) => {
                                  // primitive logic not 
                                  // worth to become a named method
                                  try { return job.Files[0].LocalName); }
                                  catch { return null as string; }
                                 }
                   };

Этот код создает следующую оправданную ошибку компилятора:

не может назначать лямбда-выражение для свойство анонимного типа

В приведенном выше коде делегат должен установить свойство FileName. Но это не моя цель. Я хочу, чтобы код работал так, но без указания метода:

var jobSummaries = from job in jobs
                   where ...
                   select new 
                   {
                        ID = job.ID,
                        Description = job.Description,
                        FileName = this.ExtractFileName(job)
                   };

...
private string ExtractFileName(Job job)
{
     try { return Path.GetFileName(job.Files[0].LocalName); }
     catch { return null as string; }
}

Любые предложения?

Ответы

Ответ 1

Чтобы вызвать анонимную функцию напрямую, это работает:

int result = new Func<int, int>( (int i) =>{ return i + 5; } ).Invoke(3);
// result = 8

Но я согласен, int result = (i => i + 5)(3); будет более холодным =)

Ответ 2

Насколько я знаю, вы не можете встраивать подобные лямбда-выражения, потому что выражение lamda - это сам экземпляр (типа Expression<Func<T>> или аналогичного).

Однако вы можете это сделать (обновляется с помощью вычисления имени файла, поскольку это теперь предоставляется OP):

var jobSummaries = from job in jobs
                   where ...
                   let fileName = job.Files.Select(f => f.LocalName).FirstOrDefault()
                   select new 
                   {
                        ID = job.ID,
                        Description = job.Description,
                        FileName = fileName
                   };

Обратите внимание на использование ключевого слова let, которое позволяет извлекать имя файла из переменной job непосредственно внутри выражения LINQ.

Ответ 3

Компилятор жалуется, потому что вы не вызываете свою лямбда-функцию, вы определяете ее. Если компилятор позволит вам, у вас будет свойство FileName, которое является функцией, а не значением.

Если вы можете написать свою "примитивную логику" как выражение, вы можете написать это непосредственно в инструкции присваивания.

Ответ 4

Как использовать расширение для выбора. Итак, вы можете сделать свою небольшую логику внутри

var jobSummaries = jobs.Select(j =>
            {
                var someVar = j + "bla";
                return new
                    {
                        somelogic = someVar
                    };

            });