I have a set of model objects that have a public IsVisible
boolean property. All I need to do is find if at least one of the set has that value set to TRUE
. In other words, if I have 10,000 objects but the second one is true
, I don't need to spin through the other 9,998. I already have my answer.
Now I know I could write my own iterating function and break out at the first 'True
' value, but I'm hoping that's something LINQ can do. Actually, it doesn't even need to be LINQ. Any suggestions are welcome.
BTW, the language of choice is C#.
Update:
See my last post here. I've added some test code and timings. Seems LINQ is pretty damn poor performance-wise compared to just doing the test myself. Sure it's easier to write, but in mission-critical timings, I'm no longer sure.
What surprised me though is most of the time I've ran these, enumeration won and by a fair clip, but for some reason, when I wrapped the test in multiple passes, it looks to have switched to indexing with a cached count as b开发者_高级运维eing fastest.
I also noticed that if I don't reset everything back to 'false', all the remaining/repeated tests seem to be MUCH faster. Somehow, re-setting everything to FALSE (which was purposely overkill to test exactly this...) changes things.
Interesting. Not sure which way I'm gonna go now. This isn't a mission-critical system so perhaps I'll go for readability, but still. Interesting.
The method you're looking for is Enumerable.Any
.
bool anyObjectsVisible = myObjects.Any(myObject => myObject.IsVisible);
This has the exact short-circuiting semantics you are looking for; the sample code is similar to:
static bool AreAnyObjectsVisible(IEnumerable<MyObject> myObjects)
{
foreach (var myObject in myObjects)
{
if (myObject.IsVisible) return true;
}
return false;
}
If you need to actually find an object, simply use the .First or .FirstOrDefault method:
var myObject = myCollection.First(x=>x.IsVisible);
or
var myObject = myCollection.FirstOrDefault(x=>x.IsVisible);
The only difference between them is that the .First method will throw an exception if there is no such object in the collection when the second one returns the default value (null in this example).
If you just need to check if there is any object with this property set, use
var thereIsVisibleObject = myCollection.Any(x=>x.IsVisible);
All of these methods stop iterating through the collection once the corresponding object is found.
Or, should you check if all of the objects are visible/invisible, you may do this:
var allTheObjectsAreVisible = myCollection.All(x=>x.IsVisible);
var allTheObjectsAreInvisible = myCollection.All(x=>!x.IsVisible);
But .All method will enumerate all of the elements (which is obvious from its name).
Here is an ".Any()" implementation:
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
foreach (TSource local in source)
{
if (predicate(local))
{
return true;
}
}
return false;
}
So here is it, nothing "special" with .Any(), it is just a wrapper around "foreach". Nothing special to test there and nothing to blame in terms of micro-micro-micro optimization.
精彩评论