Search code examples
c#linqienumerable

C# IEnumerable Return Changes after Function Parameter Changes


I was writing unit tests to compare an original response to a filtered response using a request object as a parameter. In doing so I noticed that if I change the request object after getting a response the IEnumerable list will change - As I type this, my thinking is that because it is an IEnumerable with LINQ, the request.Filter property is a reference in the LINQ query, which is what causes this behavior. If I converted this to a list instead of an IEnumerable, I suspect the behavior would go away because the .ToList() will evaluate the LINQ expressions instead of deferring. Is that the case?

public class VendorResponse {
    public IEnumerable<string> Vendors { get; set; }
}

var request = new VendorRequest() {
    Filter = ""
};

var response = await _service.GetVendors(request);

int vendorCount = response.Vendors.Count(); // 20
request.Filter = "at&t";
int newCount = response.Vendors.Count(); // 17

public async Task<VendorResponse> GetVendors(VendorRequest request)
{
    var vendors = await _dataService.GetVendors();
    return new VendorResponse {
        Vendors = vendors.Where(v => v.IndexOf(request.Filter) >= 0)
    }
}

Solution

  • If deferred execution is preferable, you can capture the current state of request.Filter with a local variable and use that in the Where predicate

    public async Task<VendorResponse> GetVendors(VendorRequest request)
    {
        var filter = request.Filter;
    
        var vendors = await _dataService.GetVendors();
    
        return new VendorResponse {
            Vendors = vendors.Where(v => v.IndexOf(filter) >= 0)
        }
    }