对IEnumerable中第一项的变量赋值不起作用

问题描述 投票:2回答:2

我试图将值true分配给我的对象集合中的字段。我使用First()方法检索第一个对象,并分配给它。在这个例子中,我将值true赋值给Show变量。然而,在分配之后,看来Show变量仍然是false

    public class CallerItem
    {
        public int IndexId;
        public string PhoneNumber;
        public bool ToInd;
        public bool Show;
    }

    public void myFunc() {
        var callers = dbCallerRecs.Select(x => new CallerItem() { IndexId = x.IndexId, PhoneNumber = x.PhoneNumber, ToInd = x.ToInd });
        var toCallers = callers.Where(x => x.ToInd);
        if (toCallers.Any())
        {
            toCallers.First().Show = true;
            Console.Log(toCallers.First().Show); //THIS LOGS 'false'. HOWEVER, IT SHOULD LOG 'true'
        }
    }

有什么我想念的吗?也许我对Where条款返回的引用的理解不对?

c# linq ienumerable
2个回答
1
投票
if (toCallers.Any())
{
    toCallers.First().Show = true;
    Console.Log(toCallers.First().Show); //THIS LOGS 'false'. HOWEVER, IT SHOULD LOG 'true'
}

每次你打电话给.First(),你都是getting the first item。对于某些枚举(例如IQueryable),它每次都会返回一个不同的对象。

以下代码只调用该方法一次,从而避免了这个问题。还要注意我使用FirstOrDefault而不是Any然后使用First - 因为前者会导致更少的DB查询(即更快)。

var caller = toCallers.FirstOrDefault().
if (caller != null)
{
    caller.Show = true;
    Console.Log(caller.Show);
}

1
投票
var callers = dbCallerRecs.Select(x => new CallerItem() { IndexId = x.IndexId, PhoneNumber = x.PhoneNumber, ToInd = x.ToInd });
var toCallers = callers.Where(x => x.ToInd);

定义一个查询,当查询生成的IEnumerable<CallerItem>(或实现IQueryable<CallerItem>IEnumerable<CallerItem>)中的某些元素时,将对其进行求值。这在你的代码中发生了三次 - 当调用Any时,你都会调用First(假设.Any()返回true)。

您看到此行为的原因是对First的两次调用导致重新评估查询并为每个调用创建一个新对象,因此您将修改另一个对象,即您最终记录的对象。

一种解决方案是热切地评估查询:

var toCallers = callers.Where(x => x.ToInd).ToList();
© www.soinside.com 2019 - 2024. All rights reserved.