Does LINQ to objects stop processing Any() when condition is true? - c#

Consider the following:
bool invalidChildren = this.Children.Any(c => !c.IsValid());
This class has a collection of child objects that have an IsValid() method. Suppose that the IsValid() method is a processor intensive task. After encountering the first child object where IsValid() is false, theoretically processing can stop because the result can never become true. Does LINQ to objects actually stop evaluating after the first IsValid() = false (like a logical AND) or does it continue evaluating all child objects?
Obviously I could just put this in a foreach loop and break on the first invalid result, but I was just wondering if LINQ to objects is smart enough to do this as well.
EDIT:
Thanks for the answers, for some reason I didn't think to look it up on MSDN myself.

Yes it does. As soon as it finds a match, the criteria is satified. All is similar in that it checks all items but if one doesn't match it ends immeditately as well.
Exists works in the same manner too.
Any
The enumeration of source is stopped as soon as the result can be determined.
Exists
The elements of the current List are individually passed to the Predicate delegate, and processing is stopped when a match is found.
All
The enumeration of source is stopped as soon as the result can be determined.
etc...

Yes, it stops as soon as the results can be evaluated. Here's a quick proof:
class Program
{
static void Main(string[] args)
{
bool allvalid = TestClasses().Any(t => !t.IsValid());
Console.ReadLine();
}
public static IEnumerable<TestClass> TestClasses()
{
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}",Environment.NewLine)); return true; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("FALSE{0}", Environment.NewLine)); return false; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
}
}
public class TestClass
{
public Func<bool> IsValid {get;set;}
}

Yes it will stop after it encounters the first item for which the condition matches, in your case the first item for which c.IsValid() returns false.
From MSDN:
The enumeration of source is stopped
as soon as the result can be
determined.

Here's a quick and dirty empirical test to see for yourself:
class Kebab
{
public static int NumberOfCallsToIsValid = 0;
public bool IsValid()
{
NumberOfCallsToIsValid++;
return false;
}
}
...
var kebabs = new Kebab[] { new Kebab(), new Kebab() };
kebabs.Any(kebab => !kebab.IsValid());
Debug.Assert(Kebab.NumberOfCallsToIsValid == 1);
The result is that yes, the Any LINQ operator stops as soon as a collection item matches the predicate.

as per MSDN,
The enumeration of source is stopped as soon as the result can be determined.

Related

How to convert float to system.Collection.generic.IEnumerable

How to convert float to system.Collection.generic.IEnumerable
The actual problem occurs when I try to iterate through the returned IEnumerable.
Code
private ObservableRangeCollection<ReviewInfo> _rating = new ObservableRangeCollection<ReviewInfo>();
public ObservableRangeCollection<ReviewInfo> Review
{
get { return _rating; }
set { _rating = value; OnPropertyChanged("AvRating"); }
}
public async Task GetReview()
{
var ber_id= berProfile.Id;
ResponseInfo<ReviewInfo> res = await nsManager.Instance.GetReview(ber_id);
Device.BeginInvokeOnMainThread(async () => {
IsBusy = false;
if (res.IsError == true)
{
await _page.Alert(res.Message);
}
else
{
if (res.Data != null && res.Data.Count > 0)
{
var temp = res.Data.Average(x => x.Rating);
Review.AddRange(temp);
}
}
});
}
Review is a collection of GogroomCustomer.Models.ReviewInfo, so you should create ReviewInfo object from temp by constructor or set via Property (ex: reviewInfo), then use Add or AddRange method:
Review.Add(reviewInfo);
or
Review.AddRange(new ReviewInfo[] { reviewInfo });
Your question is quite unclear as you didn´t provide what a ReviewInfo is. However your error is quite clear: you´re trying to add a float to a list of ReviewInfo. Of course this won´t work.
From your code I suppose this class has at least a Rating-property or field. Assuming you have a list of those ReviewInfo-instances you probably want to retrieve that object whose Rating-property is the average of all the elements within your list.
If this is the case your solution is simply this:
var temp = res.Data.Average(x => x.Rating);
Review.Add(res.Data.First(x.Rating == tmp));
However as Average returns a double it is fairly possible that there´s no element with exactly this rating in your list, so it´s better to apply some tolerance. However this goes too far on guessing what you actually want.

returning different values in an NSubstitute mock method with an out parameter

Given a method with which to mock...
public bool TryReceive(out T message, TimeSpan millisecondsToWait)
I wish to set different messages on the first two calls, and return
true.
Subsequent calls return false.
I have tried a few variations, and in either case, the lambda expression is executed once, and never again. NSubstitute seems to be caching the first return value, and using the same value over and over.
I have tried this...
TCR #out;
var container = new AutoSubstitute();
var mb = container.Resolve<IMessageBuffer<TCR>>();
mb.TryReceive(out #out, Arg.Any<TimeSpan>()).Returns(
_ => { _[0] = buy; return true; },
_ => { _[0] = sell; return true; },
_ => { _[0] = null; return false; });
and I have tried this:
bool? bs = true;
TCR #out;
var container = new AutoSubstitute();
var mb = container.Resolve<IMessageBuffer<TCR>>();
mb.TryReceive(out #out, Arg.Any<TimeSpan>()).Returns(
_ =>
{
if (bs == true)
{
_[0] = buy;
bs = false;
return true;
}
if (bs == false)
{
_[0] = sell;
bs = null;
return true;
}
_[0] = null;
return false;
});
The only option I can think of is to provide a complete substitute implementation of the buffer for test purposes. My feeling is that given this documentation, it should be possible.
edit
I have been unable to get this working using NSubstitute, however if I provide a mock implementation of the IMessageBuffer<TCR> using
// mock buffer will return the necessary values by maintaining
// the relevant state internally.
container.Provide<IMessageBuffer<TCR>>(new MockBuffer());
it works correctly, so it's not a lifetimescope issue. Somehow NSubstitute seems to be calling the mocked out method only the first time, and reusing the value (or operating in such a way that it seems to reuse the value) - very strange.
NSubstitute struggles a bit with out and ref parameters.
The problem is that when we stub:
mb.TryReceive(out #out, Arg.Any<TimeSpan>()).Returns(...)
this will only execute when #out is the original value. This value will change the first time it is called, so the Returns lambda won't execute again (NSub thinks it is a different, non-matching call).
The easiest way to work-around this is to switch to ReturnsForAnyArgs(...):
mb.TryReceive(out #out, Arg.Any<TimeSpan>()).ReturnsForAnyArgs(action0, action1, action2);
This will work for all TryReceive calls, regardless of the parameter values, so the lambda should always execute. The downside of this is that if you want this to only run for specific values of the second argument then you'll have to put that logic inside the lambda (rather than using an argument matcher).

Weird behaviour in enumerators in LINQ

According to MS documentation, the enumerator should throw InvalidOperationEx, if the underlying enumerated source was modified. This works when I just get the enumerator directly from IEnumerable.
THE PROBLEM: But if I acquire enumerator from "query data structure" , then modify the source and then call MoveNext(), nothing is thrown (see the code).
Consider following code:
public static void Main(string[] args)
{
var src = new List<int>() { 1, 2, 3, 4 };
var q = src.Where(i => i % 2 == 1);
IEnumerable<int> nl = src;
var enmLinq = q.GetEnumerator();
var enmNonLinq = nl.GetEnumerator();
src.Add(5); //both enumerators should be invalid, as underlying data source changed
try
{
//throws as expected
enmNonLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("non LINQ enumerator threw...");
}
try
{
//DOES NOT throw as expected
enmLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("enumerator from LINQ threw...");
}
//It seems that if we want enmLinq to throw exception as expected:
//we must at least once call MoveNext on it (before modification)
enmLinq.MoveNext();
src.Add(6);
enmLinq.MoveNext(); // now it throws as it should
}
It seems you must first call MoveNext() method to made it notice the change of underlying source.
Why I think this is happening:
I think this is because the "query structure" is giving you too lazy enumerator, which instead of being initialized on GetEnumerator() is initialized during first call to MoveNext().
By initialization I mean connecting all of the enumerators (from WhereEnumerable, SelectEnumerable etc structures returned by LINQ methods) on the way down to the real underlying data structure.
QUESTION:
Am I right about this or am I missing something?
Do you consider it as weird/wrong behaviour?
You are correct.
The LINQ query will not call GetEnumerator on the underlying List<T> until you call MoveNext on the IEnumerable<T> returned by Where.
You can see in the reference source that MoveNext is implemented like so:
public override bool MoveNext()
{
switch (state)
{
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext())
{
TSource item = enumerator.Current;
if (predicate(item))
{
current = item;
return true;
}
}
Dispose();
break;
}
return false;
}
In the 'initial' state (state 1), it will first call GetEnumerator on the source before moving to state 2.
The documentation only states execution is deferred until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.
Since it lacks further detail, the queries performed by LINQ may call GetEnumerator on their source either on the first call to their own GetEnumerator or as late as possible, such as the first call to MoveNext.
I wouldn't assume any particular behavior.
In practice, the actual implementation (see Enumerable.WhereEnumerableIterator<TSource> in the reference source) defers execution to the first call to MoveNext.
enmLinq is not actualized until first MoveNext call. So, any modification done to the src prior to calling MoveNext will not affect validity of enmLinq. Once you call MoveNext on enmLinq - enumerator is actualized, hence any changes on src will lead to exception for the subsequent MoveNext call.
You can test this yourself.
public static void Main(string[] args)
{
var src = new List<int>() { 1, 2, 3, 4 };
var q = src.Where(i =>
{
Output();
return i % 2 == 1;
}
);
IEnumerable<int> nl = src;
var enmLinq = q.GetEnumerator();
var enmNonLinq = nl.GetEnumerator();
src.Add(5); //both enumerators should be invalid, as underlying data source changed
try
{
//throws as expected
enmNonLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("non LINQ enumerator threw...");
}
try
{
//DOES NOT throw as expected
// Output() is called now.
enmLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("enumerator from LINQ threw...");
}
//It seems that if we want enmLinq to throw exception as expected:
//we must at least once call MoveNext on it (before modification)
enmLinq.MoveNext();
src.Add(6);
enmLinq.MoveNext(); // now it throws as it should
}
public static void Output()
{
Console.WriteLine("Test");
}
When you run the program, you will see that "Test" is not output to the console until after you call your first MoveNext, which occurs after the source was initially modified.

Dude, where's my object? or, Why does Linq not return my object?

Once I have the results of my Linq query, I am not always happy. There could be a result that I was expecting to be there but wasn't. For example, my client was expecting that a customer was in a customer list, but it wasn't. It is my client saying "Dude, where's my customer?", not me. I am the Dude, and to remain a dude, I have to give my client the reason.
Is there a simple way to take a given object instance and a Linq query and determine which expressions within the query excluded that instance?
Edit Ok, here is a better example
Output should be something along the lines:
Your Customer was excluded for 2 reasons:
Customer FirstName is Carl but it should be Daniel
Customer Age is 18 but it should be > 20
public class Customer
{
public string FirstName { get; set; }
public int Age { get; set; }
}
[Test]
public void Dude_wheres_my_object_test1()
{
var daniel = new Customer { FirstName = "Daniel", Age = 41 };
var carl = new Customer { FirstName = "Carl", Age= 18 };
var Customers = new List<Customer>() { daniel, carl };
// AsQueryable() to convert IEnumerable<T> to IQueryable<T> in
//the case of LinqtoObjects - only needed for this test, not
//production code where queies written for LinqToSql etc normally
//return IQueryable<T>
var query = from c in Customers.AsQueryable()
where c.Age > 20
where c.FirstName == "Daniel"
select c;
//query would return Daniel as you'd expect, but not executed here.
//However I want to explain why Carl was not in the results
string[] r = DudeWheresMyObject(query, carl);
Assert.AreEqual("Age is 18 but it should be > 20", r[0]);
Assert.AreEqual("FirstName is Carl but it should be Daniel", r[1]);
//Should even work for a Customer who is not
//in the original Customers collection...
var ficticiousCustomer = new Customer { FirstName = "Other", Age = 19};
string[] r2= DudeWheresMyObject(query,
ficticiousCustomer);
Assert.AreEqual("Age is 19 but it should be > 20", r2[0]);
Assert.AreEqual("FirstName is Other but it should be Daniel", r2[1]);
}
public string[] DudeWheresMyObject<T>(IQueryable<T> query, T instance)
{
//Do something here with the query.Expression and the instance
}
First of all, before I attempt to write some fancy Fluent framework, Has anyone done this already?
So far, I have considered navigating the expression tree and executing each branch against an IQueryable that only contains my object. Now I don't have a great deal of experience using raw expression trees, so I would like those who have to suggest any pitfalls or even explain whether this is a dead end and why.
I am anxious that anything that results from this should:
Be Reusable - Should be applicable to any object compared against a Linq query returning objects of the same class.
Not affect the performance of the original query (this should just be standard Linq).
Should be Linq-implementation agnostic.
If there are multiple property values set on the missing instance that excluded it from the results, then all of those reasons should be reported.
Edit
I am not suggesting that I keep executing LinqToSql against the database multiple times with different permutations of the query and comparing the results. Rather, I am looking for a way to take a single instance and compare it to the expression tree (without executing the query directly again)
Also, I would like an indication of whether others might find this useful. If so, I would consider starting an open source project to solve it.
I think you'd have to re-create the query as linq-to-objects and deal with the subtle differences between linq-to-sql/entities/whatever and linq-to-objects, accepting that some providers just won't work realistically.
You have your object you want to find in an in memory IEnumerable<T> or something.
You'd have to walk the expression tree somehow and snip out the leaves, so say you had:
where obj.foo == true && obj.bar == "yes"
you'd have to figure out that obj.foo == true and obj.bar == "yes" are leaves and start there. It'd be a sort of depth first search of the expression tree.
So, construct linq to objects queries that only had those leaves. See if the object is included in the results. If not then we've found out why it's excluded, if not then go up the tree (i.e. make the where query include more clauses, getting closer to the orignal one until the object disappears from the results).
As I see it the tough parts would be handling the differences between original linq to 'whatever' and link to objects, figuring out where to split the where claues, dealing with things like joins which can also exclude things and dealing with things like SqlMethods.Like that don't work in linq to objects.
For a one-off exploration of what's filtering out the result, it's hard to beat the Dump method in LINQPad. Here's an extract from one of their samples that shows it in action:
// Dump returns exactly what it was given, so you can sneakily inject
// a Dump (or even many Dumps) *within* an expression. This is useful
// for monitoring a query as it progresses:
new[] { 11, 5, 17, 7, 13 } .Dump ("Prime numbers")
.Where (n => n > 10) .Dump ("Prime numbers > 10")
.OrderBy (n => n) .Dump ("Prime numbers > 10 sorted")
.Select (n => n * 10) .Dump ("Prime numbers > 10 sorted, times 10!");
This gives nicely formatted tables of results:
With some fun expression hacking, you can see the results of each stage of the evaluation for each item in the set. Inspect the local result after the breakpoint has been hit to see the results of the evaluation. To actually use the results of the evaluation, just append .Where(x => x.IsIncludedInResult).Select(x => x.EvaluationTarget) to the line where the report is generated.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication4
{
[DebuggerDisplay("{Condition} on {EvaluationTarget} is {EvaluationResult}")]
public class ReportItem<T>
{
public string Condition { get; private set; }
public IEnumerable<ReportItem<T>> NestedReports { get; private set; }
public object EvaluationResult { get; private set; }
public T EvaluationTarget { get; private set; }
public ReportItem(Expression condition, IEnumerable<ReportItem<T>> nestedReports, T evaluationTarget, object evaluationResult)
{
Condition = condition.ToString();
NestedReports = nestedReports;
EvaluationTarget = evaluationTarget;
EvaluationResult = evaluationResult;
}
public override string ToString()
{
return string.Format("{0} on {1} is {2}", Condition, EvaluationTarget, EvaluationResult);
}
}
[DebuggerDisplay("Included: {IsIncludedInResult} \n{Summary}")]
public class Report<T>
{
public ReportItem<T> Contents { get; private set; }
public T EvaluationTarget { get; private set; }
public Report(T source, Expression<Func<T, bool>> predicate)
{
EvaluationTarget = source;
IsIncludedInResult = predicate.Compile()(source);
Contents = Recurse(predicate.Parameters.Single(), predicate.Body, source);
}
private object Evaluate(Expression expression, ParameterExpression parameter, T source)
{
var expr = Expression.Lambda(expression, parameter);
var #delegate = expr.Compile();
var value = #delegate.DynamicInvoke(source);
return value;
}
private ReportItem<T> Recurse(ParameterExpression parameter, Expression sourceExpression, T source)
{
var constantExpression = sourceExpression as ConstantExpression;
if(constantExpression != null)
{
return new ReportItem<T>(sourceExpression, null, source, Evaluate(constantExpression, parameter, source));
}
var unaryExpression = sourceExpression as UnaryExpression;
if(unaryExpression != null)
{
var content = Recurse(parameter, unaryExpression.Operand, source);
var result = Evaluate(sourceExpression, parameter, source);
return new ReportItem<T>(sourceExpression, new[]{content}, source, result);
}
var binaryExpression = sourceExpression as BinaryExpression;
if(binaryExpression != null)
{
var left = Recurse(parameter, binaryExpression.Left, source);
var right = Recurse(parameter, binaryExpression.Right, source);
var item = new ReportItem<T>(sourceExpression, new[] {left, right}, source, Evaluate(sourceExpression, parameter, source));
return item;
}
var methodCallExpression = sourceExpression as MethodCallExpression;
if(methodCallExpression != null)
{
var args = methodCallExpression.Arguments.Select(x => Evaluate(x, parameter, source)).ToArray();
var result = methodCallExpression.Method.Invoke(Expression.Lambda(methodCallExpression.Object, parameter).Compile().DynamicInvoke(source), args);
return new ReportItem<T>(sourceExpression, null, source, result);
}
throw new Exception("Unhandled expression type " + sourceExpression.NodeType + " encountered");
}
public bool IsIncludedInResult { get; private set; }
public string Summary
{
get { return Contents.ToString(); }
}
public override string ToString()
{
return Summary;
}
}
public static class PredicateRunner
{
public static IEnumerable<Report<T>> Report<T>(this IEnumerable<T> set, Expression<Func<T, bool>> predicate)
{
return set.Select(x => new Report<T>(x, predicate));
}
}
class MyItem
{
public string Name { get; set; }
public int Value { get; set; }
public override int GetHashCode()
{
return Value % 2;
}
public override string ToString()
{
return string.Format("Name: \"{0}\" Value: {1}", Name, Value);
}
}
class Program
{
static void Main()
{
var items = new MyItem[3];
items[0] = new MyItem
{
Name = "Hello",
Value = 1
};
items[1] = new MyItem
{
Name = "Hello There",
Value = 2
};
items[2] = new MyItem
{
Name = "There",
Value = 3
};
var result = items.Report(x => !x.Name.Contains("Hello") && x.GetHashCode() == 1).ToList();
Debugger.Break();
}
}
}
It's kind of a tricky one, as in, from your example you could always code something to check for specifics and report 'I searched for term x and the object i returned was not in term x'.
I would have though as others suggested though, that this would have been along the lines for 'return me x' then in code, run a query for 'x where x.property = y' and report non matches.
Following this through, I'd imagine the issue would be that in order to generate the list of non matches, your query or object graph would become pretty massive as you'd need your original object either initially include (or to be expanded via lazy loading to include) many permutations to determine the matches or not.
This is kind of the inverse of running a query on the first place where you'd start with an object and sub select based on conditions, you'd want to select and then selectively super select, catching non conditions.
It's an interesting problem, and one that I'd normally address either client side or code wise before getting to a point where and object was returned or not. But I guess the perfect solution would be to return a single solution and perhaps examine it's associations for links.
The links wouldn't be too hard to find a generic "I've not got one of these" type reason, but to give a 'I've got this link, not that link' response would be harder.
You'd need to maybe provide a method based on some form of predicate builder which took a field and search term and returned an appropriate message if things didn't match. In my mind seems like two slightly different problems.
Slightly rambling now, but would be curious to hear any answers to this!...
I think I follow what you mean. What I think you would want to do is perform two queries, one with selection criteria, and one without, then perform a Linq Except on them to determine which items were excluded, then walk that list and determine what criteria caused them to be excluded.
I can't really think of a better way to do it.
Something like this:
var a = db.Trades.Where(z => z.user == x && z.date == y);
var b = a.Where(z => z.TradeCurrency != null && z.TradeUnderlying.Index != null);
var c = a.Except(b);
List<string> reasons;
foreach(var d in c) {
if (d.TradeCurrency == null)
// add reason
... etc..
}
This would perform a single query (which would have several sub-queries) and only return the results that were excluded (rather than trying to return all results which could be quite large). Unless of course you have a million excluded records and only a few included ones.
Not sure how efficient this is, though compared to a way I can't think of.
EDIT:
I think you are forgetting that Linq queries do not execute until you call an operation that realizes them. In this example, the database is only hit once, even though there are several linq query objects here. The expression tree is modified without executing the queries.
So in this example, when the foreach() occurs, a single database query (with several sub-queries) is executed.

Code structure, a methods should only do one thing

I am having a bit following the "a method should only do one thing"
I have a car text file, and if it contains even one BMW I want to set isValid to true, but while I am going through the text file anyways I thought I would also populate two list high end models(M3,M5 etc) and lower model (335, X3 etc).
I know that method should only do one thing, but it seems so convenient for it to also populate the lists. Here is what I have:
private bool hasBMWegments()
{
foreach (ClassLib.CarSegment carElement in CarSegmentFactory.ContainsCar("BMW"))
{
isValid = true;
if (carElement.Class.IndexOfAny(lowerModels) == 0)
{
lstOlderSegment.Add(carElement.ElementNumber);
}
if (carElementClass.IndexOfAny(upperModels) == 0)
{
lstNewerSegment.Add(carElement.ElementNumber);
}
}
return isValid;
}
Should I just create a method that performs the foreach check again? Or should I create another method inside that method (I would think that would be messy, and wouldn't related to the method name)
edit: sorry working with framework 2.0
I find that code to be a mess compared to this:
private IEnumerable<ClassLib.CarSegment>
GetModels(IEnumerable<ClassLib.CarSegment> segments, string modelID)
{
return segments.Where(x => x.Class.IndexOfAny(modelID) == 0);
}
// ...
var bmwSegments = CarSegmentFactory.ContainsCar("BMW").ToArray();
bool isValid = bmwSegments.Any();
var olderModelSegments = GetModels(bmwSegments, lowerModels);
var newerModelSegments = GetModels(bmwSegments, upperModels);
This code is obviously correct at a glance. The other code makes you look twice at the loop to figure out what's going on.
It looks like all you're doing is setting isValid to true on the first pass through the foreach. So all isValid really means is "is there at least one element?".
In which case you do not need to iterate twice. You can use Any() to do the valid check:
bool IsValid(IEnumerable<CarSegment> elements)
{
return elements.Any();
}
void PopulateSegments(IEnumerable<CarSegment> elements)
{
foreach(var element in elements)
{
//add to lists
}
}

Categories

Resources