我有一个排除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'
该方法将被调用(其中values
为IEnumerable<string>
且x.zipcode
为string
):
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
答案 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; }
}
}