I have the following LINQ query that fires an exception when the FirstOrDefault() returns null. Ideally I would like to avoid the null check. Is there a way to do this? I wish to return 0 if there are no CPOffsets that satisfy the FirstOrDefault() call.
double offset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime).CPOffset;
The only way I can see to achieve this is the following:
CPOffset cpOffset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime);
double offset = cpOffset != null ? cpOffset.CPOffset : 0;
Is there another more succinct way? Using Select() after the FirstOrDefault() doesn't compile but I thought might be appropriate here?
I think this should work, I'm not near by VS to check it out...
OrderedOffsets.Where(o => o.OffsetDateTime > cpTime).Select(x => x.CPOffset).FirstOrDefault();
DefaultIfEmpty can be used to ensure that the collection always has at least one element.
double offset = OrderedOffsets.Where(o => o.OffsetDateTime > cpTime)
.Select(o => o.CPOffset)
.DefaultIfEmpty()
.First();
I think a good pattern could be :
double offset = (OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime) ?? someDefaultObject).CPOffset;
with someDefaultObject an object holding default values... With this pattern, you can change easily you default values through your code !
If OrderedOffsets can be a struct you could also just put your default value there ! :)
Related
I can use a converter for this task, but my situation is this:
I've an object with several properties, I evaluate the double of each property and return the result of a function, the code explain better:
var partialFinalForecast = poisson.GetPartialFinalForecast();
partialFinalForecast.GetType().GetProperties()
.Where(x => x.PropertyType == typeof(double)).ToList()
.ForEach(x => x.SetValue(partialFinalForecast, Math.Round((double)x.GetValue(partialFinalForecast), 2)));
sometimes happen that this return NAN, how can I avoid this result directly on this query?
You could replace (double)x.GetValue(partialFinalForecast) with Double.IsNaN((double)x.GetValue(partialFinalForecast)) ? 0 : (double)x.GetValue(partialFinalForecast), but this is hardly a good approach (as mentioned by oerkelens)...
could you please help me!
I have object list like:
item[0].title = apple
item[0].data.weight = 1
item[1].title = lemon
item[1].data = null
item[2].title = melon
item[2].data.weight = 3
I would like to sort it (ASC and DESC) by weight with null data.
I tried like this:
item.OrderBy(x => x.data == null).ThenBy(x => x.data.weight); // failed
item.Where(x => x.data != null).OrderBy(x => x.data.weight); // ok, but as result only two records
So how i can sort items and receive all results.
ASC at first should be data with null.
DESC at first data with max weight and null at the end of the list.
item.OrderBy(x => x.data == null).ThenByDescending(x => x.data == null ? 0 : x.data.weight);
I am assuming weight is an int, otherwise provide the default value based on type.
Given you're only shipping fruit, and not, say, light, you can treat items having null data as having weight 0. Alternatively, just pick any value that's lower than the possible, valid values in order to put the null items at the top when sorting ascendingly.
You can express that like this:
var ordered = item.OrderBy(x => x.data == null ? 0 : x.data.weight);
You could use something like this: (assuming C# 6 or above)
item.OrderBy(x => x.data?.weight ?? int.MinValue);
This makes use of the new C#6 null-conditional and null-coalescing operators - if you need something applicable in lower versions of C#, you can use a ternary operator, like this:
item.OrderBy(x => x.data != null ? x.data.weight : int.MinValue);
If it's possible that you could have x.data.weight being int.MinValue, then you would need to do something like what you were doing before, but the second linq method should make use of the above lambda/s.
You can do this a few ways, one way would be to have a value replacing the null values using ternary conditional operator on the order by or filtering out the items without a value and concatenating them to the enumerable after you've sorted the objects with values.
By conditionally providing a value for items with null
This is, in my opinion, the best way, and it performs better. You only enumerate over the collection once, versus the other method where you enumerate to determine if each element has a value then order, and then check for the items without a value
item.OrderBy(x => x.data != null ? x.data.weight : int.MinValue)
Filtering and then concatenating the items without a value
There are times where this could possibly be the better solution. One example would be if you want to use a different method for ordering the values when they are missing the property you are looking for.
item.Where(x => x.data != null)
.OrderBy(x => x.data.weight)
.Concat(item.Where(a=>a.data == null))
I have come across a scenario where i am summing in my LINQ query.
The property could have actually NULL in database.
However, when we apply aggregate i.e. SUM on same field in collection using LINQ it calculates/returns 0 for null
I am avoiding sum for null field as following.
TotalDays = x.Select(y => y.day.HasValue ? x.Sum(z => z.day) : null).FirstOrDefault(),
Is it nice way or could have even better?
Null values sum to zero because naturally they can neither add nor subtract to the tally so generally one wants zero in such cases.
Consider:
(new int?[]{0, null, 3, 2}).Sum() // result is 5. Other linq providers do similar.
Where this can sometimes cause a problem is if you want to note all-null result-sets separately:
(new int?[]{null, null}).Sum() // result is 0, but maybe we want to note that there was indeed no values.
We could do this with:
source.Any(x => x.HasValue) ? source.Sum() : default(int?);
Which to bring back to your example would be:
int? totalDays = x.Any(y => y.day.HasValue) ? x.Sum(y => y.day) : default(int?);
However you might prefer to do:
int? totalDays = x.Sum(y => y.day);
if (totalDays == 0 && y.All(y => !y.day.HasValue))
totalDays = null;
Then you only examine the set to see if all values are null in the case of receiving the 0 result (any other result is not possible in this case).
Checking Any() first is more efficient when all-null results are more common, and doing Sum() first is more efficient when all-null results less common, because in each case you are only doing two operations in the less common case.
I have this code
folderList = (List<SPFolder>)folderList.OrderBy(folder => Object x = folder.GetProperty("Order Folder By"); x == null ? 0 : (int)x;).ToList();
But it's giving me a syntax error.
Does anyone know whats wrong here?
Thanks.
You're not returning anything. You need to return the value in a statement lambda. You also need to wrap the statements in curly braces to use multiple statements in a lambda. You also can't treat a conditional operator as an expression; it needs to be a statement.
They're fixed with the same fix.
folderList = (List<SPFolder>)folderList.OrderBy(folder => {
Object x = folder.GetProperty("OrderFolderBy");
return x == null ? 0 : x;}).ToList();
That said, you can do the whole thing with just an expression instead; there's no need to use multiple statements:
folderList = folderList.OrderBy(folder => folder.GetProperty("OrderFolderBy") as int?).ToList();
There also no reason for that cast. The list should already be of the appropriate type, and both null and 0 come before other numbers, so there's no real reason for the null check at all.
You need the braces since you had two statements in the lambda and you also need the cast to object for the ? : operator
folderList = folderList.OrderBy(
folder =>
{
Object x = folder.GetProperty("OrderFolderBy");
return x == null ? (object)0 : x;
}).Cast<SPFolder>().ToList();
You can avoid using the intermediate assignment to x by using the null coalescing operator ??.
folderList = folderList.OrderBy(
folder => folder.GetProperty("OrderFolderBy") ?? (object)0)
.ToList();
I use ADO.NET entity framework and very often there are code snippets like this :
List<Sole> entity = soleService.All()
.Where(s => (s.ShoeLastID == shoeLastID) && (s.Status == 20))
.ToList();
Since now I haven't think much about it and just made this check:
if (entity.Count > 0)
believing that it is enough. Now I see that many people check with Any() and for null. How to be sure at a certain situation what kind of checks I need and in this certain scenario which as I said - I use very often is if (entity.Count > 0) enough?
if (entity.Count > 0) or if (entity.Any()) are identical in you case. As you already fetched all the data from the DB, the list has been built and you knows its size. So .Count property doesn't iterate over anything.
In the other hand, do not call the .Count() IEnumerable extension if you didn't fetched all data, because it'll enumerate items for nothing.
Use instead:
bool test = soleService.All()
.Any(s => (s.ShoeLastID == shoeLastID) && (s.Status == 20));
if (test)
{
...
}
Also, LINQ extensions won't return null but an empty IEnumerable, so don't check for null.
If you have a .ToList() call, then the list is always a list. Maybe empty, but never null.
The check for .Any() instead of .Count() > 0 is a performance improvement for most containers or enumerables because .Any() will only touch the first element if there is one. .Count() would need to count through your container to the end although you are not interested in the result, only in the fact that it's not zero.
Depends on what you need.
If you just want to know if any of entities match your predicate then use Any(), as it will return immediately upon finding the first matching entity.
Count() / Count will need to process all the entities which will typically be much slower.
Also prefer Linq's Count() to List Count as it doesn't have to create the full list in the memory, which can be very expensive with large result sets.
Any() will provide better solution cause it stopse after first matching.
in addition
I would suggest also to do ToList() only if Any() is true.
Youll save (micro) performance.
var t = soleService.All() .Where(s => (s.ShoeLastID == shoeLastID) && (s.Status == 20));
if (t.Any()) entity =t.ToList();
When you call if (entity.Count > 0) but entity == null, you will get an exception because .Count does not exist while entity is not initialized.
Of course a list can be null or empty. If you attempt to create a List<Sole> using LINQ as above and the soleService could be null, in which case you will get a NullReferenceException. So I would check that the soleService is not null or empty first. So
List<Sole> entity = null;
// ...
if (soleService != null && soleService.Count > 0)
entity = soleService.All()
.Where(s => (s.ShoeLastID == shoeLastID) && (s.Status == 20))
.ToList();
I hope this helps.
entity.Any() - will return true if there is any entities in your collection. entities.Count() == 0 will do the same. But I would recommend to use any because it will work faster. Because Count will return the amount of data in the collection, but any will trigger on the first item found in your collection.
But if you are not sure that your collection is initialized I would recommend you to use next construction:
if(entity!=null && entity.Any())
{
//Do something. You will get her always without error, And you will be 100% sure that your collection is not empty and it is initialized
}
Hope it helps.
entity.Any() is better choice. And you don't need to invoke .ToList() since this wll take all the data from the database and then just check its count.