使用double,float或decimal而不是int时,LINQ查询不会编译

时间:2017-11-10 19:15:56

标签: c# linq

考虑以下简化示例,该示例在搜索对象列表的代码之后建模,并通过为每个对象分配分数来对其进行排序以尝试计算相关性(实际代码中的得分细节不相关)这里):

public class MyClass
{
    public string UserName { get; set; }
    public string UserDescription { get; set; }
}

public static void QueryTest()
{
    var somequerytext = "test";
    var accounts = new List<MyClass>();
    var resultsViaInt = accounts.Where( ( MyClass acct, int score ) => 
            MatchInt( acct.UserName, somequerytext, ref score, 2 ) ||
            MatchInt( acct.UserDescription, somequerytext, ref score, 1 ) 
        )
        .Select( ( acct, score ) => new { result = acct, score = score } )
        .OrderBy( x => x.score )
        .Select( x => x.result )
        .ToList();

    var resultsViaDouble = accounts.Where( ( MyClass acct, double score ) => 
            MatchDouble( acct.UserName, somequerytext, ref score, 2.0 ) ||
            MatchDouble( acct.UserDescription, somequerytext, ref score, 1.0 )
        )
        .Select( ( MyClass acct, double score ) => new { result = acct, score = score } )
        .OrderBy( x => x.score )
        .Select( x => x.result )
        .ToList();
}


public static bool MatchInt( string haystack, string needle, ref int score, int weight )
{
    if ( haystack.Contains( needle ) )
    {
        score = score + weight;
        return true;
    }
    return false;
}

public static bool MatchDouble( string haystack, string needle, ref double score, double weight )
{
    if ( haystack.Contains( needle ) )
    {
        score = score + weight;
        return true;
    }
    return false;
}

由于某种原因,编译器在QueryTest()中为第二个查询抛出the following errors

对于“帐户”变量:

'List<MyClass>' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where<MyClass>(IQueryable<MyClass>, Expression<Func<MyClass, bool>>)' requires a receiver of type 'IQueryable<MyClass>'

对于查询本身内的lambda表达式:

Delegate 'Expression<Func<MyClass, bool>>' does not take 2 arguments

如果我尝试使用doublefloatdecimal,我会收到相同的错误。但是,使用int可行。我可以使用稍微更大的整数而不是双精度来完成剩下的工作,但我想知道上面的代码为什么不能编译。

第二个错误看起来很奇怪,因为第一个查询的等效部分被检测(正确)为<Func<MyClass, int, bool>>,而带有错误的查询缺少对中间参数的任何引用。

为什么它只适用于int

2 个答案:

答案 0 :(得分:3)

我认为这与您所寻找的非常接近。

        var resultsViaDouble = accounts
            .Select(acct =>
            {
                double score = 0;
                return new
                {
                    match = MatchDouble(acct.UserName, somequerytext, ref score, 2.0) || MatchDouble(acct.UserDescription, somequerytext, ref score, 1.0),
                    score = score,
                    acct = acct
                };
            })
            .Where(x => x.match)
            .OrderBy(x => x.score)
            .Select(x => x.acct)
            .ToList();

关于OP中的方法有什么问题,我认为评论已经足够彻底地解释了它。

答案 1 :(得分:2)

有效的Where方法的重载是:

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, int, bool> predicate
)

List<MyClass>是IEnumerable)

int参数代表序列中元素的索引

double参数

没有这种重载

所以你在这里错误地使用了int score

我建议你改变这样的代码:

public static double MatchDouble(string haystack, string needle, double weight )
{
    return haystack.Contains( needle ) ? weight : 0;
}
var resultsViaInt = accounts
    .OrderBy( 
              acct => MatchDouble( acct.UserName, somequerytext, 2.0 ) +
                      MatchDouble( acct.UserDescription, somequerytext, 1.0 )  
            )
    .ToList();