DefaultIfEmpty行为细节

时间:2016-03-19 19:08:51

标签: c# linq

最近我遇到了这个问题,花了一些时间才弄明白。我有这样的代码:

private Member FindMemberByName(string name)
{
    var member =
        this.db.Members.AsEnumerable()
        .Where(d => d.ShortName == name)
        .DefaultIfEmpty(this.CreateNewMember(name))
        .First();
    return member;
}

private Member CreateNewMember(string name)
{
    return this.db.Members.Add(new Member { Name = name });
}

我希望FindMemberByName()返回现有实体,如果缺席,则创建新实体并返回一个实体。

但是我注意到,即使传递了现有名称,也会调用CreateNewMember()。

2 个答案:

答案 0 :(得分:4)

您询问的行为与LINQ无关。您在DefaultIfEmpty()参数列表中放置的方法将在调用DefaultIfEmpty()之前进行评估。您可以通过编写一个类似的方法来看到这一点,该方法不会引用传入的默认对象。

void Main()
{
    CalledMethod(CreateDefault("Hello World"));
}

void CalledMethod<TSource>(TSource defaultValue)
{
}

TestClass CreateDefault(string message)
{
    return new TestClass() { Message = message, };
}

public class TestClass
{
    public string Message { get; set; } = null;
    public TestClass() { }
}

答案 1 :(得分:3)

稍微调试一下后我就明白,即使没有调用DefaultIfEmpty()方法,也会立即评估First()参数的值。所以实际上它是在了解生成的IEnumerable是否为空之前进行评估的。

我花了几个小时试图找出问题所在。希望这可以帮助其他人节省相同的时间: - )