默认情况下,linq过滤器无法显示?

时间:2016-06-08 18:39:53

标签: c# linq

我一直在努力在LINQ中重写一些命令式代码,直到我意识到自己缺少了什么。但我不知道为什么这是一个问题。考虑以下。测试无法使用

运行Test.Test2(testList)
  

序列不包含匹配元素

过去,我对这些表单进行了交替处理,通过将我的谓词推送到FirstSingle等语句来编写更小的代码。显然,当涉及DeafultIfEmpty时,我不能这样做。这是因为使用WhereFirstSingle等不可互换?或者,是因为DefaultIfEmpty子句引入了并发症吗?

编辑1 我添加了一个测试,表明FirstOrDefault不起作用。它失败了"未找到"不等于(null)。

public static class Test
{
    public static string Test1(params string[] input)
    {
        return input
            .Where(x => x == "apples")
            .DefaultIfEmpty("bannanas")
            .First();
    }

    public static string Test2(params string[] input)
    {
        return input
            .DefaultIfEmpty("bannanas")
            .First(x => x == "apples");
    }

    public static string Test3(params string[] input)
    {
        return input
            .DefaultIfEmpty("bannanas")
            .FirstOrDefault(x => x == "apples");
    }
}

public class TestStuff
{
    [Fact]
    public static void TestOneAndTwo()
    {
        var testList = new string[] { "oranges", "pears", "pineapples" };
        var one = Test.Test1(testList);
        var two = Test.Test2(testList);
        Assert.Equal(one, two);
    }

    [Fact]
    public static void TestOneAndThree()
    {
        var testList = new string[] { "oranges", "pears", "pineapples" };
        var one = Test.Test1(testList);
        var three = Test.Test3(testList);
        Assert.Equal(one, three);
    }
}

3 个答案:

答案 0 :(得分:2)

LINQ方法的顺序很重要,请考虑每个方法对输入可枚举({ "oranges", "pears", "pineapples" })的作用:

public static string Test1(params string[] input)
{
    return input
        .Where(x => x == "apples") // empty enumerable, because no item matches "apples"
        .DefaultIfEmpty("not found") // {"not found"}, since the enumerable is empty
        .First(); //"not found", since we have this item
} 

public static string Test2(params string[] input)
{
    return input
        .DefaultIfEmpty("not found") // { "oranges", "pears", "pineapples" }
                                     //i.e., nothing changes, because input is not empty
        .First(x => x == "apples"); //Exception because there is no
                                    //item that is equal to "apples"
}

如果您将最后一种方法从First更改为FirstOrDefault,则会生成null,因为default(string)null

答案 1 :(得分:1)

你应该使用FirstOrDefault(),这样当数组没有任何匹配时,会返回一个默认值,而不是抛出异常。

编辑:

Test1中,在Where子句之后,结果序列变为空。应用DefaultIfEmpty后,生成的序列将包含单个元素"not found"

Test2中,当应用DefaultIfEmpty时,序列尚未过滤。因此,传递相同的序列。但是,当First(predicate)尝试减少序列时,没有任何内容可以出现,这就是InvalidOperationException发生的原因。

答案 2 :(得分:0)

我同意Xiaoy312。 FirstOrDefault方法更好。然后检查一下它是否为空。

public static string Test2(params string[] input)
{
     return input.FirstOrDefault(x => x == "apples")
}