C# check null on an object and its property - c#

I'd like to tidy up this piece of code, any idea?
1 object is not null
1 of its property is not null either
var v = Values.Find(x => x.id.Equals(Properties.Resources.myString));
if (v != null && v.Property != null)
{
// do something with 'v.Property'
}

C# 6.0 will probably best serve you here with the null conditional operator:
var v = Values.Find(x => x.id.Equals(Properties.Resources.myString));
var result = v?.Property?.DoSomething();

Related

How can I use the new collasce features to make these 2 statments into 1 line?

Using the new C# features for null checks, could I reduce these 2 lines into one and still ensure it is safe to do so? i.e. no null errors
var carTypes = #Model.CarSubTypes.FirstOrDefault(x => x.LookupId == item.SubType);
var carTypeName = carTypes!= null ? carTypes.Name : "";
You should be able to write:
var carTypeName = #Model.CarSubTypes.FirstOrDefault(x => x.LookupId == item.SubType)?.Name
?? "";
The ?. operator check if the left operand is null : if it is not it evaluates Name else it stops the evalutation of the expression and the operator ?? let you define the value used for the assignment.

Null value in linq where clause

I'm having an issue where I want to return results where something matches and I get an error if one of the properties I'm trying to match is null.
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
x.FirstName.ToLower().Contains(searchString) ||
x.LastName.ToLower().Contains(searchString) ||
x.ContractNum.ToLower().Contains(searchString) ||
x.VIN.ToLower().Contains(searchString) ||
x.Claim.InitiatedBy.ToLower().Contains(searchString)
).ToList();
}
If ContractNum or VIN, for example, are null then it throws an error. I'm not sure how to check if one of these are null inside of a linq query.
You can add explicit null checks:
Infos = Infos.Where(
x =>
(x.FirstName != null && x.FirstName.ToLower().Contains(searchString)) ||
(x.LastName != null && x.LastName.ToLower().Contains(searchString)) ||
(x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) ||
(x.VIN != null && x.VIN.ToLower().Contains(searchString)) ||
(x.Claim != null && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString))
).ToList();
You have multiple options, first is to do an explicit check against null and the other option is to use Null propagation operator.
x.FirstName != null && x.FirstName.ToLower().Contains(searchString)
or
x.FirstName?.ToLower()?.Contains(searchString) == true
But I would suggest you to use IndexOf instead of Contains for case
insensitive comparison.
something like:
x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) >= 0)
Checking the property is null or empty before comparing it it's the only way I know
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
(!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) ||
(x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString))
).ToList();
}
EXTRA: I added a check on the Claim property to make sure it's not null when looking at InitiatedBy
EXTRA 2: Using the build in function IsNullOrEmpty to compare string to "" and nullso the code is clearer.
Extra 3: Used of ToLowerInvariant (https://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx) so the lowering action will act the same no matter of the culture.
You could use ?? to replace it with a acceptable value.
(x.ContractNum??"").ToLower()
I would use the null conditional operator ?, this will however, return a nullable bool? so you will need to handle that appropriately.
Some examples on how to do this:
x?.FirstName?.ToLower().Contains(searchString) == true;
x?.FirstName?.ToLower().Contains(searchString) ?? false;
An alternative method to keep the comparison logic in one place to use a sub collection of the properties and check on those:
Infos = Infos.Where(i=>
new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/}
.Any(w=> w?.ToLower().Contains(searchString) ?? false))
.ToList();
(It does read out all properties, but that shouldn't cost much performance and gains much maintainability )

Null object in Func

I have a filter as below:
filter = project => project.Plan.ProgressStatus == progressStatus;
I am creating a filter based on progressStatus that is passed into method.
Then I pass this filter to a where operator.
var projects = _projectService.Where(filter);
I get back NRE since Plan is null.
How can I safely query objects whose Plan.ProgressStatus is equal to what i pass in as parameter?
Make your filter check if it is null:
filter = project => project.Plan != null && project.Plan.ProgressStatus == progressStatus;
If _projectService possibly contains null then add that check as well:
filter = project => project != null
&& project.Plan != null
&& project.Plan.ProgressStatus == progressStatus;
Add a null check to the project and/or project.Plan objects in your func.
filter = project =>
{
if(project == null || project.Plan == null)
return false;
return project.Plan.ProgressStatus == progressStatus;
};

Better Way to Check for Null Value in Linq Path

Here is an example of an assignment to a linq path pulled from code first...
applicants = appRegistrations
.ToList()
.Select(c => new ApplicantList() {
PartnerType = c.Participant != null ? c.Participant.PartnerType != null ? c.Participant.PartnerType.PartnerTypeName : "" : ""
});
Notice the null checks - is there a more elegant way I can write this code considering Participant AND PartnerType could be null?
I just hate checking for nulls on each property.
You could check if one of both are null:
List<ApplicantList> applicants = appRegistrations
.Select(ar => c.Participant == null || c.Participant.PartnerType == null
? "" : c.Participant.PartnerType.PartnerTypeName)
.Select(str => new ApplicantList { PartnerType = str })
.ToList();
You can shorten it a little bit:
PartnerType = c.Participant != null && c.Participant.PartnerType != null
? c.Participant.PartnerType.PartnerTypeName
: ""
When you construct the objects such as Participant, make sure that the properties are never null. Think if null is a valid value for a Participant? If not then you should never allow it to be null. Take a constructor parameter and add a guard clause to check for nulls. Otherwise initialize them to a default value.
Also, see NULL Reference Pattern.

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.

Categories

Resources