2011-02-04 2 views
3

私はこれを行う方法があることを知っていますが、私はそれを把握しようと壁に私の頭を叩いています。これはうまく動作します:linqで匿名デリゲートを選択

private GenericRecord CreateGeneric(GenericRecord g, Member m) 
{ 
    g.Member = m; 
    return g; 
} 

public IList<GenericRecord> ReportFromDatabase(DateTime startDate, DateTime endDate) 
{ 
    List<GenericRecord> returnRecords = new List<GenericRecord>(); 

    returnRecords.AddRange(from r in pjRepository.Records 
          join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
          where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
          select CreateGeneric((GenericRecord)r, m)); 

    return returnRecords; 
} 

しかし、私はCreateGeneric関数なしでそれを行う方法があることを知っています。デリゲート関数をインラインで選択するにはどうすればよいですか?私は、この例外を与える

returnRecords.AddRange(from r in pjRepository.Records 
         join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
         where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
         select (delegate 
         { 
          GenericRecord g = (GenericRecord)r; 
          g.Member = m; 
          return g; 
         })); 

The type of the expression in the select clause is incorrect. Type inference failed in the call to 'Select'. 

編集:文で

ラムダ式を:もう一つの失敗した試みは

returnRecords.AddRange((from r in pjRepository.Records 
         join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
         where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
         select new { r, m }).Select(x => 
         { 
          GenericRecord g = (GenericRecord)x.r; 
          g.Member = x.m; 
          return g; 
         })); 

これは私に与え b odyは式ツリーに変換できません。

答えて

12

試してみてください。

returnRecords.AddRange((from r in pjRepository.Records 
          join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
          where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
          select new { r, m }).AsEnumerable().Select(x => 
          { 
           GenericRecord g = (GenericRecord)x.r; 
           g.Member = x.m; 
           return g; 
          })); 

異なる鍵は、そのAsEnumerable()関数です。これはIQueryableをとり、IEnumerableを返します。これは、背後でLinqプロバイダによる式ツリーの評価を強制します。これにより、Linqライブラリが2番目のSelectのラムダを式ツリーの一部に変換しようとしないようにします(これはできません)。 2番目のSelectは代わりに、IQueryable式ツリーを評価することによって生成された実際のメモリコレクションに対してその変換を実行します。文が途中で終了する前に(すべての要素をreturnRecordsに追加できるように)クエリを評価する必要があるため、パフォーマンスに大きな違いはありません。

+0

ブリリアント!ありがとうございました! –

0
Seem like this is what you are looking at: 
class Bila 
    { 
     public string Name; 
     public List<string> Adresses; 
    } 
    var justNumbers = Enumerable.Range(0, 10); 
Func<int,List<string>> foo = delegate(int j) 
    { 
     List<string> lst = new List<string>(); 
     for (int kk = 0; kk < j; kk++) 
     { 
      lst.Add("String_" + kk.ToString()); 
     } 
     return lst; 
    }; 
var zilla3 = (from x in justNumbers 
       select new Bila 
       { 
        Name = "Name_" + x.ToString(), 
        Adresses = foo(x), 
       }).ToArray(); 
+0

は何らかの説明を提供する。 – Parixit

関連する問題