麻烦匿名方法

时间:2013-02-04 19:51:34

标签: c# linq-to-sql lambda anonymous-types

我有一个排除IEnumerable<T>和lambda表达式的方法,该表达式描述了用于将linq-to-sql集合与数组进行比较的字段。该方法返回匹配的记录。

public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, 
        Func<ZipCode, T> matchPhrase) {
    return (from zipCode in _table
            where values.Contains<T>(matchPhrase)
            select zipCode).Distinct();
}

我收到了错误:

  

参数类型'Func<ZipCode, T>'无法分配参数类型'T'

该方法将被调用(其中valuesIEnumerable<string>x.zipcodestring):

var zipCodes = _zipCodeRepository.match(values, x => x.zipcode)

更新

基于John关于使用HashSet<T>的建议我已经更改了我的代码但是现在我遇到了不同的错误

  

方法'System.Object DynamicInvoke(System.Object [])'没有支持的SQL转换。

我想我可能不清楚我的问题,我认为我使用错误的方法签名来获得我想要的结果。让我用一个更简单的代码示例来解释:

public IEnumerable<ZipCode> match(IEnumerable<string> values) {
    return (from zipCode in _table
            where values.Contains(zipCode.zipcode)
            select zipCode).Distinct();
}

我正在努力实现这一目标但是使用匿名类型。我想通过lambda传递到Contains()中使用的字段。因此zipCode.zipcode将作为第二个参数传递给方法:x => x.zipcode

3 个答案:

答案 0 :(得分:2)

我怀疑你想调用代表:

return (from zipCode in _table
        where values.Contains(matchPhrase(zipCode))
        select zipCode).Distinct();

请注意,这可能会非常昂贵。您可能想先创建一个集:

HashSet<T> valueSet = new HashSet<T>(values);
return _table.Where(x => valueSet.Contains(matchPhrase(x))
             .Distinct();

(我在这里删除了查询表达式,因为它在可读性方面弊大于利。)

答案 1 :(得分:1)

您忘记了(zipCode)

中的Contains
public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, Func<ZipCode, T> matchPhrase) {
    return (from zipCode in _table
            where values.Contains(matchPhrase(zipCode))  // <- Here (and you don't need to specify <T>, the compiler deduce it from the argument)
            select zipCode).Distinct();
}

您可以使用Join方法获得更好的性能(O(n)中的复杂性):

public IEnumerable<ZipCode> match<T>(IEnumerable<T> values, Func<ZipCode, T> matchPhrase)
{
    return (from zipCode in _table
            join value in values on matchPhrase(zipCode) equals value
            select zipCode).Distinct();
}

答案 2 :(得分:1)

包含只接受字符串作为参数,而不是表达式。您将无法在此级别对其进行参数化。

您可以将整个where部分作为参数传递:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ConsoleApplication
{
    class Program
    {
         static void Main(string[] args)
         {
             var values = new List<string>();
             values.Add("123");

             Console.WriteLine(
                 Match(zip => values.Contains(zip.Code)).Count()); // -> 1

             Console.WriteLine(
                 Match(zip => values.Contains(zip.OtherCode)).Count()); // -> 0

             Console.Read();
         }

         public static IEnumerable<ZipCode> Match(Expression<Func<ZipCode, bool>> predicate)
         {
             var table = new List<ZipCode> 
                      { new ZipCode { Code = "123" }, new ZipCode { OtherCode = "234" } }
                .AsQueryable();

             return (from zipCode in table.Where(predicate)
                    select zipCode).Distinct();
         }
     }
     public class ZipCode
     {
         public string Code { get; set; }

         public string OtherCode { get; set; }
     }
}