Назначение свойства анонимного типа через анонимный метод - PullRequest
14 голосов
/ 03 марта 2010

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

Учитывая следующий НЕПРАВИЛЬНЫЙ код:

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; }
}

Есть предложения?

Ответы [ 4 ]

16 голосов
/ 03 марта 2010

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

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

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

3 голосов
/ 03 марта 2010

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

Тем не менее, вы можете сделать это ( обновлено с вычислением fileName, так как теперь это обеспечивается 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.

2 голосов
/ 03 марта 2010

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

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

0 голосов
/ 13 февраля 2013

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

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

            });
...