objLst = objLst.FindAll(c => c.Emp_cod.Equals(string.Empty)
|| c.Emp_cod.Equals(null))
I am having a List of All Employees and New Employees who have been offered has emp_cod value null.
Now when i am trying to find New Employees using the above code it gives object reference error.
Emp_cod column is string defined as below when imported from SQL to DBML:
[Column(Storage = "_Emp_cod", DbType = "VarChar(10)")]
public string Emp_cod { get; set; }
You can try:
objLst = objLst.Where(c => String.IsNullOrEmpty(c.Emp_cod));
The reason you are getting the error is because you are trying to call instance method Equals on null object. You need to check for null first and then check for string empty.
objLst = objLst.FindAll(c => c.Emp_cod != null && c.Emp_cod.Equals(string.Empty));
Or better if you may use string.IsNullOrEmpty like Adrian's answer.
You may also try string.IsNullOrWhiteSpace if you want to check against, null, empty and white spaces, but only if you are using .Net 4.0 or higher
objLst = objLst.FindAll(c => string.IsNullOrWhiteSpace(c.Emp_code))
Related
I'm basically trying to iterate over a lot of data and transform a returned data query to a more limited object within a View Model.
Rather than do a huge section of code, I'm calling .ForEach() on a list, then adding a new entry to the view model's list.
This works great, but, there is one property (Address) that is optional.
When I reach the optional item, I get NullReferenceException if the item from the DB doesn't have an entry.
A code example is:
var tmp = _context.Person.Include(x => x.Address).ToList();
tmp.ForEach(x => vm.List.Add(new IndexListItem()
{
Name = x.Name,
Address = x.Address.FirstLine + " " + x.Address.SecondLine,
ID = x.ID
}));
I have since found out from a different answer on this site that if I change the address line so that it reads:
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
The code now works when I hit a null entry in tmp.
I do not understand this as the Address property on tmp was already allowing nulls, and the Address property on the view model allows nulls, so, why does changing the line suddenly not return an error?
In addition, is the reason for me not having to do x.Address?.FirstLine? because that's a string and strings are already nullable?
A null reference exception in this particular case is caused when you are trying to access a property where the parent object is null itself.
x.Address.FirstLine
i.e. in your case Address is null.
It is not in regard to what you are trying to set (i.e. the destination view model).
The reason that this works:
x.Address?.FirstLine
..is because 'in the background' it's checking first to see if Address is null. If it isn't, then it returns FirstLine and if it is, then null is returned. It's semantically equivalent to:
if (x.Address == null)
{
return null;
}
else
{
return x.Address.FirstLine;
}
Here's a blog post about the introduction of the ?. operator in C# for some background reading: https://blogs.msdn.microsoft.com/jerrynixon/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator/
I do not understand this as the Address property on tmp was already allowing nulls, and the Address property on the view model allows nulls, so, why does changing the line suddenly not return an error?
You are mixing up saving data with loading data. When you save the data to the database, null is acceptable, but when you try to use the data, null is not.
The null conditional operator (?.) allows you to "shorten" an if statement, and it would be something similar to:
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
string Address = "";
if (x.Address != null)
{
Address += x.Address.FirstLine;
}
// ....
Also, while not relevant to your problem, the code you are using is extremely ineffective, you are loading 2 tables to get just a few properties when you could get those properties directly from the database:
var vm = _context.Person
.Select(x => new IndexListItem
{
Name = x.Name,
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
ID = x.ID
})
.ToList();
x.Address?.FirstLine where ? is null propogation operator this means if x.Address is null set null for the FirstLine.
null propogation equivalent code
if (x.Address == null)
return null
else
return x.Address.FirstLine
All reference type variables are nullable. hence, assigning null to reference types are always valid.
string is a reference-type in your example. therefore you do not get error because string x = null is valid
Your issue isn't that Address is null and you're trying to assign it to another property that allows null, it's that you're trying to access .FirstLine in something that's null.
If Address is null, then what you're trying to do with .FirstLine is the equivalent of null.FirstLine which doesn't work. Nothing can't hold something.
The ? notation you're using that works is only effecting Address, basically saying if Address is NOT null give me the value of .FirstLine, if it is null, then give me null.
I'm using C# in Visual Studio and I have a table with an attribute set to allow nulls, I try to get a query excluding null values like so:
var playerQueryDel = (from p in DB.Jugadores
where p.goles != null
orderby p.goles
select new
{
tiros = p.tirosPorteria,
goles = p.goles,
nombre = p.nombreJugador
}
).ToList();
Where goles is an attribute of type int that accepts nulls and I know that there are some records in the database with null values in this attribute, the problem is that is returns "empty" values, for example trying this:
System.Diagnostics.Debug.WriteLine($"Testing: {playerQueryDel[0]}");
Prints this:
Testing:
I also try to print to know if it is emptry like so:
System.Diagnostics.Debug.WriteLine($"{playerQueryDel[0] == null}");
Prints false, what is the cause of this "not null but empty" value and is there a way to check without having to parse it to something else?
I'll upload more information if needed :)
A couple of things to try: Check that the list contains any items. Check the individual field in the result being returned.
System.Diagnostics.Debug.WriteLine($"Testing: {playerQueryDel.Count}");
System.Diagnostics.Debug.WriteLine($"Testing: {playerQueryDel[0].goles}");
I am using C# 6 and I have the following:
public class Information {
public String[] Keywords { get; set; }
}
Information information = new Information {
Keywords = new String[] { "A", "B" };
}
String keywords = String.Join(",", information?.Keywords ?? String.Empty);
I am checking if information is null (in my real code it can be). If it is than join a String.Empty since String.Join gives an error when trying to join null. If it is not null then just join information.Keywords.
However, I get this error:
Operator '??' cannot be applied to operands of type 'string[]' and 'string'
I was looking on a few blogs and supposedly this would work.
Am I missing something?
What is the best alternative to do this check and join the string in one line?
As the types must match on either side of the ?? (null-coalescing) operator you should pass a string array, in this case you could pass an empty string array.
String keywords = String.Join(",", information?.Keywords ?? new string[0]);
The best alternative would be to check for null before joining the strings:
var keywords = information?.Keywords == null ? "" : string.Join(",", information.Keywords);
Example
Have a look at the following code:
private void DeDuplicateOrganisations()
{
var profileOrgs = _organisations.Where(o => o.ExistsInProfile).ToList();
var kvkOrgs = _organisations.Where(o => !o.ExistsInProfile).ToList();
profileOrgs.ForEach(o =>
{
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
_organisations = profileOrgs.Concat(kvkOrgs).OrderBy(o => o.Title).ToList();
}
In this example the property CompanyInfoOrganisation (simply a get; set; property) is copied when an organisation is considered a duplicate. This all works as expected, duplicates are nicely deduplicated.
Also this is true inside this message:
_organisations.First(o => o.ExistsInBoth).CompanyInfoOrganisation != null;
Problem
Now I bind the _organisations list to a listbox
lbxCompanies.DataSource = null;
lbxCompanies.DataSource = _organisations;
lbxCompanies.DisplayMember = "Title";
lbxCompanies.SelectedIndex = -1;
and later on get the selected value:
var org = lbxCompanies.SelectedValue as Organisation;
gbxCompanyInfo.Visible = org != null;
if (gbxCompanyInfo.Visible)
if (org.CompanyInfoOrganisation != null)
// NEVER GETS HERE (but gbxComanpyInfo is visible)
If I try to read the CompanyInfoOrganisation property I always get null while I know the property was set.
Question
What is happening here? How come the property reference is destroyed? How can I prevent this from happening?
The reference you're using only has immediate scope and as soon as the query ends it exits scope and your reference disappears. So when you bind later, the reference is exactly right -- null.
profileOrgs.ForEach(o =>
{
// Right here -- var duplicate has scope ONLY within your query.
// As soon as the query is executed it leaves scope and the reference
// pointer will be null
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
Because you're using a class, you need to perform a deep MemberwiseClone on it to get a NEW copy of the object:
o.CompanyInfoOrganisation = (YourInfoType)duplicate.CompanyInfoOrganisation.MemberwiseClone();
When you load the data, load the CompanyInfoOrganisation property along with the root entity; that way it will be already loaded into memory. If using LINQ to SQL, you load via DataLoadOptions, and pass this to the context. If using Entity Framework, you use the Include method in the LINQ query.
It might have to do with capturing of variables inside the lambda. Try substituting the .ForEach to a regular foreach().
Or maybe the CompanyInfoOrganisation in duplicate was null to begin with.
The problem was I used string.Join() to show the values, and the first value to join was null (which is really annoying), resulting in an empty string, leaving me thinking the property was null. However it turned out the property was not null, but has a perfectly valid reference to the object needed. Using the debugger with a little more care would have saved me an hour or so...
Sorry!
I have a model class
public class Item
{
public string Name {get; set;}
public string Desc {get; set;}
}
I would query my XML document
List<Item> item = xmlDoc.Descendants()
.Select(o => new Item {
Name = o.Attribute("name").Value,
Desc = o.Attribute("desc").Value
}).ToList();
However, the attribute desc may or may not be present for each item. The above LINQ works if the attribute desc is present, but will cause an exception if not.
If it does not exist I would like for the LINQ query to just assign null to the Desc field in the new Item object. Thank you for any suggestions.
The right way to do this is with the conversion operators:
Name = (string) o.Attribute("name"),
Desc = (string) o.Attribute("desc")
why is this the preferred way? Firstly, it is easy; and secondly, it works correctly for other types:
Count = (int?) o.Attribute("count"),
When = (DateTime?) o.Attribute("when")
In particular, these also apply the correct xml encoding rules for each data type, rather than using a culture-specific DateTime.Parse / int.Parse etc. Lots of subtle things to not want to remember!
Note that if you want to assert that the attribute exists, the non-Nullable<T> versions work too:
Size = (int) o.Attribute("size"),
Created = (DateTime) o.Attribute("created")
You can use the ternary operator - ?:
List<Item> item = xmlDoc.Descendants()
.Select(o => new Item {
Name = o.Attribute("name") != null ? o.Attribute("name").Value : null,
Desc = o.Attribute("desc") != null ? o.Attribute("desc").Value : null,
}).ToList();