I am too new to LINQ.
public static Dictionary<Type, ConfigurationObjectBase> MyDictionary;
This expression returns "Object reference not set to an instance of an object":
MyDictionary.First(o => o.Value.ID == 12).Key;
In fact, the object with ID = 12 is there.
Update:
In fact, the object with ID = 12 is there
it means, there is objects within dictionary where ID is 12.
If there were no such item, then it would throw InvalidOperationException with message "Sequence contains no matching element".
It means that either:
your Dictionary is not initialized. You said that there is an object with ID = 12. So, it means that is it initialized.
there is at least one item in your dictionary where a value is null. So, while iterating, it tries to access its Value.ID and throws a NullReferenceException.
Imagine a simple loop over an array:
ConfigurationObjectBase Search()
{
ConfigurationObjectBase[] array = { someObject1, someObject2, null, someObject3 };
foreach (var item in array)
{
if (item.ID == 12) return item;
// here, if item is null, you will try to access its ID and get NullReferenceException
}
throw new InvalidOperationException("Sequence contains no matching elements");
}
Actually, that's what LINQ exactly does. It iterates through the dictionary and once it tries to access a property of null, it throws an exception.
You may use the following code to avoid accessing the property of null:
MyDictionary.First(o => o.Value != null && o.Value.ID == 12).Key;
If there is an object with ID 12 it means that your dictionary contains objects which are null. You can filter for them:
MyDictionary.Where(x=>x.Value!=null).First(o => o.Value.ID == 12).Key;
It will skip all objects with null Value. I prefer chaining here, because it shows intention clearly.
EDIT:
as #Yeldar Kurmangaliyev said this answer is good only for small dictionaries. If you want to go with big dictionaries better do:
MyDictionary.First(o => o.Value!=null && o.Value.ID == 12).Key;
Related
I am confused. I have two statements that are the same and one works and the other receives the error - value cannot be null. r nparameter name source. From what I read I am receiving the error because something is null in my linq expression. However from what I can tell nothing is null.
The first if statement works. When a person selects 'Select' from a list of Burn Project a list of BurnPiles is displayed below the BurnProject list. (this works). Then when a person selects 'Select' from the list of BurnPiles a list of RequestedBurns is display below it. This gives me the null error. At one time it did work now it doesn't.
I am at a loss of what went wrong. I do know the RequestedBurn Table starts at record #2 but that shouldn't have anything to do with it. The BurnPile records that I have been using have associated RequestedBurns.
//when 'Select' is chosen from the list of burn projects the list of burn piles
//associated with that specific burn project is display below it.
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
}
//when 'Select' is chosen from the list of burn piles the list of requested
//burns associated with that specific burn pile is displayed below it.
if (burnPileID != null)
{
ViewBag.BurnPilesID = burnPileID.Value;
viewModel.RequestedBurns = viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single().RequestedBurns;
}
If you look at documentation for Where or Single, you would see that source is the name of the parameter that represents your collection. So, it looks like you are trying to call a method on null reference, which would be the case if viewModel.BurnProjects = null or viewModel.BurnPiles = null.
viewModel.BurnPiles = viewModel.BurnProjects.Where(
b => b.BurnerID == burnerID.Value).Single().BurnPiles;
could be setting viewModel.BurnPiles to null.
or
viewModel.BurnPiles.Where(
x => x.BurnPilesID == burnPileID).Single()
is returning nothing so when you try and access RequestedBurns then it throws an exception.
SingleOrDefault also has an overload where you can simplify the expression a bit more. You can also combine it with the null conditional operator (if using at least C# 6).
if (burnerID != null)
{
ViewBag.BurnerID = burnerID.Value;
viewModel.BurnPiles = viewModel.BurnProjects.SingleOrDefault(b => b.BurnerID == burnerID.Value)?.BurnPiles;
}
I have this code:
foreach (var parent in #CurrentPage.AncestorsOrSelf().OrderBy("Level").Skip(2).Take(1))
{
...
}
The #CurrentPage.AncestorsOrSelf().OrderBy("Level").Skip(2).Take(1) returns always one result, which is right. In this there is no sense to use foreach loop when the result is only one.
How can i store the result from #CurrentPage.AncestorsOrSelf().OrderBy("Level").Skip(2).Take(1) inside a variable?
You can call .First() or .FirstOrDefault() to get the actual object:
var value = #CurrentPage.AncestorsOrSelf().OrderBy("Level").Skip(2).First();
The difference between them is that First() will throw an exception if there are no items, while FirstOrDefault() will return default(T) (that is, null for reference types and e.g. 0 for ints etc).
Since you're extracting the first item, you don't need Take(1).
I have the algorithm that select a data from collection of reportData
private IDictionary<Guid, JobStatistic> GetAgentsStatistics(IList<Guid> agentIds)
{
var agentReportItems = from data in reportData
from agentId in data.AgentIds
where agentIds.Contains(agentId)
group data by agentId;
...
}
But what if agentIds is an empty collection? How to check this situation?
var agentReportItems = from data in reportData
from agentId in data.AgentIds
where agentIds != null && agentIds.Contains(agentId)
group data by agentId;
Just check if it's null, and if it's not, then use it as you already did.
The logic you've posted will work for an 'empty collection'
However, assuming you meant null instead of 'empty', this is what an ArgumentNullException would be used for.
Throwing ArgumentNullException
private IDictionary<Guid, JobStatistic> GetAgentsStatistics(IList<Guid> agentIds)
{
if (agentIds == null)
throw new ArgumentNullException("agentIds"); // use nameof(agentIds) instead of "agentIds" if using C# 6 or later
var agentReportItems = from data in reportData
from agentId in data.AgentIds
where agentIds.Contains(agentId)
group data by agentId;
//...
}
You can quickly check if an enumerable is empty using .Any()
if (!agentIds.Any()) //It's empty.
{
throw new ArgumentException("agentIds cannot be empty.");
}
Be aware that 'null' does not mean the list is empty. Null would be a complete absence of the list.
I have a list of objects as ICollection<objectA> listA. Now I'm trying to loop thru this listA and trying to match a condition and assign the result found into a variable. I tried below:
varB.someDesc = listA.FirstOrDefault(x=>x.ID == varB.ID).someDesc
Error complaining that x.ID is object null reference. When I put a break point, I can see there are many items in listA and there is an attribute ID. May I know what goes wrong?
I suggest validating the return value of FirstOrDefault() as follows:
var item = listA.FirstOrDefault(x=>x.ID == varB.ID);
if (item != null)
varB.someDesc = item.someDesc;
The error might not be exactly what you think it is.
Try this code.
varB.someDesc = listA.Where(x=>x.ID == varB.ID).FirstOrDefault().someDesc
you better check Object Null before assigning.
I have a LINQ query like so:
var Item = (from s in contextD.Items where s.Id == Id select s).ToList();
Further down the Item object properties are set like so:
Item.FirstOrDefault().Qty = qtyToUpdate;
Item.FirstOrDefault().TotalPrice = UItem.FirstOrDefault().Qty * UItem.FirstOrDefault().Price;
...
My question is, will calling FirstOrDefault always loop through the result set returned by the query?
Shouldn't a single call be made and put in an object like so:
MyObject objMyObject = new MyObject;
objMyObject = Item.FirstOrDefault();
and then go about setting objMyObject properties.
The first part using FirstOrDefault is actually in the production, I am trying to find out if that's the right way.
Regards.
will calling FirstOrDefault always loop through the result set
returned by the query?
FirstOrDefault() never loops through all result set - it either returns first item, or default if set is empty. Also in this particular case even enumerator will not be created - thus you are calling FirstOrDefault() on variable of List<T> type, simply item at index 0 will be returned (if list is not empty). If you will investigate Enumerable.FirstOrDefault() implementation:
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (list.Count > 0)
{
return list[0];
}
}
But this will be invoked each time you are calling FirstOrDefault().
Also you are missing 'default' case. If you are chaining methods like in your first sample, you can get NullReferenceException if list is empty. So, make sure something was returned by query:
var item = Item.FirstOrDefault();
if (item == null)
return; // or throw
item.Qty = qtyToUpdate;
var uitem = UItem.FirstOrDefault();
if (uitem == null)
return; // or throw
item.TotalPrice = uitem.Qty * uitem.Price;
One more note - you have little difference in performance if you are performing FirstOrDefault() on in-memory collection. But difference will be huge if you will perform it without saving query results into list. In that case each FirstOrDefault() call will cause new database query.