【问题标题】:Assigning property of anonymous type via anonymous method通过匿名方法分配匿名类型的属性
【发布时间】:2010-03-03 13:17:09
【问题描述】:

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

此代码产生以下合理的编译器错误:

无法将 lambda 表达式分配给 匿名类型属性

上面的代码会将委托设置为 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; }
}

有什么建议吗?

【问题讨论】:

    标签: c# lambda anonymous-types anonymous-methods


    【解决方案1】:

    要直接调用匿名函数,这样可以:

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

    但我同意,int result = (i =&gt; i + 5)(3); 会更酷 =)

    【讨论】:

      【解决方案2】:

      据我所知,您不能像这样内联 lambda 表达式,因为 lamda 表达式本身就是一个实例(Expression&lt;Func&lt;T&gt;&gt; 或类似类型)。

      但是,您可以这样做(更新了文件名的计算,因为这现在由 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 关键字的使用,它可以让您直接在LINQ 表达式中从job 变量中提取文件名。

      【讨论】:

      • 我刚试过。我无法使用“let”将 lambda 表达式设置为局部变量。我更新了示例代码。我有一个 try/catch,这使得直接计算变得困难。
      • 不,您不能将 lambda 表达式分配给 fileName。只需编写代码:let fileName = Path.Combine(job.Folder, job.File) 或任何您需要的逻辑...
      • @GarbageGuy:我更新了我的答案以反映您更新的问题,因为我知道您需要的算法。请注意,不需要 try/catch。
      • 也许我错过了什么,但我不明白这一点。如果逻辑可以作为单个表达式进行计算,我可以直接在属性赋值中内联它。但它包含 try/catch(请参阅更新的代码示例),因此它既不适用于 'let' 也不适用于直接赋值。
      • 在您的特定示例中,try/catch 构造不是必需的(请参阅我的更新答案以获得更好的解决方案)。如果您的问题是更复杂的占位符,那么您是正确的,这并不能解决您的问题。您可以使用此处提供的其他解决方案之一,但我个人认为,如果您将复杂代码封装在单独的方法或类中,代码会更清晰。 YMMV。
      【解决方案3】:

      编译器抱怨是因为你没有调用你的 lambda 函数,而是定义它。如果编译器允许,您将拥有一个 FileName 属性,它是一个函数而不是一个值。

      如果您可以将“原始逻辑”编写为表达式,则可以直接在赋值语句中编写。

      【讨论】:

        【解决方案4】:

        如何使用扩展进行选择。所以你可以在里面做你的小逻辑

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多