How can I use a lambda expression in a while loop condition? - c#

while(list.next() != null && list.next().asInteger() != 6)
{
...
}
Is it possible to use an inline lambda function here to avoid calling list.next() twice? If next() actually removed the element from the list, this would be essential not just convenient.

YourType foo;
while ((foo = list.next()) != null && foo.asInteger() != 6)
{
}

You can use for instead of while:
for (var item = list.next(); item != null && item.asInteger() !=6; item = list.next()) {
...
}

You can assign variables in while loops. It would be easier to write it like so.
WhateverNextReturns nextListItem;
while ((nextListItem = list.next()) != null) && nextListItem.asInteger() != 6)
// Do some stuff
Or better yet...
WhateverNextReturns nextListItem;
while(true)
{
nextListItem = list.next();
if (nextListItem == null || nextListItem == 6)
break;
//Do some stuff
}
I think using a lambda would make this more complex than what it has to be.
Here's another example in this StackOverflow Answer of someone assigning a variable in a while expression

It is possible to do this with an inline lambda, but C# does not like it:
while (((Func<YourType, bool>)(n => n != null && n.asInteger() != 6))(list.next()))
{
...
}

is this list an IEnumerable object? You can always use
list.Where(t!=null && t=>t.asInteger()==6).ToList().ForEach(t=>{
//do anything you want with t here.
});
Tell me if I got the question wrong.

Related

Linq strange behavior

Statment:
(definitions != null && definitions.Where(key => key.asset_id != null &&
key.asset_id == item).FirstOrDefault() != null
Throws:
collection was modified enumeration operation may not execute
How to fix this?
if (definitions != null
&& definitions
.Where(key => key.asset_id != null && key.asset_id == item)
.FirstOrDefault() != null)
{
CurrentDuration = definitions
.Where(key => key.asset_id != null && key.asset_id == item)
.FirstOrDefault().duration;
}
The problem is that somewhere in your code the definitions collection is modified. Mostly it's because of collection modification in another thread, but it could have some other reasons. You should find out the piece of code which is modifying collection somewhere else. You can protect the definitions variable using a lock wherever you're using definitions.
if (definitions != null)
{
lock (definiitons)
{
var definition = definitions.FirstOrDefault(key => key.asset_id != null && key.asset_id == item);
if (definition != null)
CurrentDuration = definition.duration;
}
}
and put lock everywhere you're modifying the definitions or its references, for example:
lock (definitions)
{
definitions.Add(x);
}
or
lock (definitions)
{
definitions.Remove(x);
}
or even
var otherRef = definitions
lock (otherRef )
{
otherRef .Add(x);
}
I assume that "CurrentDuration" is a foreach loop variable counter.
The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add ,remove or change items from the source collection to avoid unpredictable side effects. If you need to add, remove or change items from the source collection, use a for loop.

c# Linq to Objects - FirstOrDefault performance

We're trying to optimize some of our methods. We use Redgate's Performance profiler to find some performance leaks.
Our tool uses Linq to objects in several methods. But we have noticed that a FirstOrDefault takes very long on collections with +/- 1000 objects.
The profiler also alerts that the query is very slow. I've added images with the profiler results.
It's not possible to add the collection to a database and then query the database.
Any recommendations?
Thanks !
private SaldoPrivatiefKlantVerdeelsleutel GetParentSaldoPrivatiefKlantVerdeelsleutel(SaldoPrivatiefKlantVerdeelsleutel saldoPrivatiefKlantVerdeelsleutel, SaldoGebouwRekeningBoeking boeking, int privatiefKlant)
{
SaldoPrivatiefKlantVerdeelsleutel parentSaldoPrivatiefKlantVerdeelsleutel = null;
if (saldoPrivatiefKlantVerdeelsleutel != null)
{
try
{
parentSaldoPrivatiefKlantVerdeelsleutel = saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection
.FirstOrDefault(s => (boeking == null || (s.SaldoVerdeelsleutel != null &&
(s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID)))
&& s.PrivatiefKlant.ID == privatiefKlant);
}
catch (Exception ex)
{ }
}
return parentSaldoPrivatiefKlantVerdeelsleutel;
}
Image :
Profile report
You should be able to speed it up by rewriting it as
saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection
.Where(s => (boeking == null || (s.SaldoVerdeelsleutel != null &&
(s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID))) && s.PrivatiefKlant.ID == privatiefKlant)
.FirstOrDefault()
See Why is LINQ .Where(predicate).First() faster than .First(predicate)? for why this is faster.
I'll say that this
boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID
could be the culprit. Try caching it outside, like:
var id = boeking != null ? boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID : 0;
and use the id inside the query.
(I'm doing a supposition: one of the properties of that long chain do something "not too much smart" and is in fact quite slow)
FirstOrDefault do standard linear search over source collection and returns first element that matches a predicate. It's O(n), so it's not surprising that it takes more time on bigger collections.
You can try following, but the gain won't be huge, because it's still O(n).
private SaldoPrivatiefKlantVerdeelsleutel GetParentSaldoPrivatiefKlantVerdeelsleutel(SaldoPrivatiefKlantVerdeelsleutel saldoPrivatiefKlantVerdeelsleutel, SaldoGebouwRekeningBoeking boeking, int privatiefKlant)
{
SaldoPrivatiefKlantVerdeelsleutel parentSaldoPrivatiefKlantVerdeelsleutel = null;
if (saldoPrivatiefKlantVerdeelsleutel != null)
{
try
{
var query = saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode
.SaldoPrivatiefKlantVerdeelsleutelCollection
.Where(s => s.PrivatiefKlant.ID == privatiefKlant);
if(boeking != null)
{
var gebouwVerdeelSleutelId = boeking.SaldoGebouwRekeningVerdeling
.SaldoGebouwRekening
.SaldoVerdeelsleutel
.GebouwVerdeelSleutel
.ID;
query = query.Where(s => s.SaldoVerdeelsleutel != null &&
s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == gebouwVerdeelSleutelId);
}
parentSaldoPrivatiefKlantVerdeelsleutel = query.FirstOrDefault();
}
catch (Exception ex)
{ }
}
return parentSaldoPrivatiefKlantVerdeelsleutel;
}
It will make better, because boeking != null check will be done only once, not on every source collection element. And because nested Where calls are combined they will not cause performance penalty.
You can try write it like a simple code. LINQ is using delegates this is why there is a little perfomance hit.
try
{
parentSaldoPrivatiefKlantVerdeelsleutel = null;
foreach (var s in saldoPrivatiefKlantVerdeelsleutel.AfrekenPeriode.SaldoPrivatiefKlantVerdeelsleutelCollection)
{
if ((boeking == null || (s.SaldoVerdeelsleutel != null && (s.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID == boeking.SaldoGebouwRekeningVerdeling.SaldoGebouwRekening.SaldoVerdeelsleutel.GebouwVerdeelSleutel.ID))) && s.PrivatiefKlant.ID == privatiefKlant)
{
parentSaldoPrivatiefKlantVerdeelsleutel = s;
break;
}
}
}
catch (Exception ex)
{ }

Variable Declaration inside an IF C#

take a look at the following code :
if( down == null || down.GetFace() != Face.None || down.GetFace() != Face.Partial )
{
// I called GetFace() two times
// How can i avoid to call it two times, and still putting inside that if
}
Thank you!
To be more maintainable and expressive first separate the null check as exceptional case
then get the result to a variable and check it.
if(down == null)
// Some exceptional case .. return or throw exception
var result = down.GetFace();
if(result == Face.None || result != Face.Parial)
// Do your code here
Refactor to a method:
private bool IsFaceNoneOrPartial(Down down)
{
var face = down.GetFace();
return face != Face.None || face != Face.Partial;
}
// Your code is now:
if( down == null || IsFaceNoneOrPartial(down))
{
}

more short code about if statement

i wanted to try the following code:
//all arrays are List<T> type.
if (m.terms[0] != null && m.terms[0].labels != null && m.terms[0].labels[0].title == "Part-of-speech")
{
result = true;
}
but it occured runtime error occasionly in following situation
i. m.terms == null
ii. m.terms != null, but m.terms[0] does not intialized.
iii. m.terms != null, and m.terms[0] has been exist but
m.terms[0].label does not initialized.
...
so i did modify it to like this:
if (m.terms[0] != null)
{
if (m.terms[0].labels != null)
{
if (m.terms[0].labels[0].title == "Part-of-speech") { result = true; }
}
}
is it the best way?
&& is a short circuiting operator, so the first way you wrote it and the second way will be functionally equivalent.
if (a && b && c)
{
// work
}
b will only be evaluated if a returns true. (Same goes for c).
In your code, checking m.terms[0].labels will not be a problem because you would have short-circuited out of the expression if m.terms[0] had been null.
To completely cover yourself, you'd want to possibly add checks for m and m.terms, however.
m != null && m.terms != null && m.terms.Count > 0 && m.terms[0] != null ...
As it evaluates from left to right, it will break on the first condition that doesn't pass and the rest will go unchecked.
int index = 0;
int labelIndex = 0;
string titleToCheck = "Part-of-speech";
if (m != null && m.terms != null && m.terms.Count > index)// or m.Length...
{
if (m.terms[index] != null && m.terms[index].labels != null &&
m.terms[index].labels.Count > labelIndex)
{
if (m.terms[index].labels[labelIndex].title == titleToCheck)
{
result = true;
}
}
}
This is all about readability. C# uses Short-circuit evaluation so in functionality there is no difference.
try this
if (m!=null && m.terms!= null && m.terms[0].labels!=null && m.terms[0].labels[0].title!=null && m.terms[0].labels[0].title == "Part-of-speech")
Yes, it would be better to split off each null check into a separate if statement.
The reason is that the second and third conditions require the first to not be null. If the first is null, then the second and third conditions will in turn throw errors because their parent is null yet is trying to be accessed.

Null check ObservableCollection before querying it

Is this code good enough:
if (MyCollection.Where(p => p.SomeID == idstring).Any())
{
selectedval = MyCollection.Where(p => p.SomeID == idstring).FirstOrDefault().MyField;
}
My doubt is about the fact that I make the same query twice: first for null check and then to actually get data.
Maybe there is a better way to do this type of things?
Yes.
var item = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if (item != null)
selectval = item.MyField;
This avoids double querying the collection, which will certainly make a difference in big collections or if your collection performs a DB query.
There is. You can use the FirstOrDefault method which takes a predicate and returns null if the item is not found.
var result = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if( result != null )
{
// item was found
}

Categories

Resources