Complex if statement never gets executed - c#

I have this long if statement that is checking for multiple things. It never seems to execute the code in the curly brackets though.
It is checking two objects.
"currentEngineObject" is the object as it exists in the database.
"engineList" is the object that is passed into this method.
So I am trying to check to make sure that the SizeId is not empty and also has a value for both objects.
If they both have values, but they are not the same value, I want to set the "SizeId" of engineList to the "SizeId" value that is in "currentEngineObject".
But even with test data, it never gets through the large if statement I have.
So I am wondering if there is a problem with my logic? Like should I be using "Or" instead of "And"?
Here is my if block:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& (currentEngineObject.SizeId.Value != engineList.SizeId.Value))
{
engineList.SizeId = currentEngineObject.SizeId.Value;
}
Thanks!

Try this:
if ((currentEngineObject.SizeId.HasValue && currentEngineObject.SizeId.Value != Guid.Empty)
&& (engineList.SizeId.HasValue && engineList.SizeId.Value != Guid.Empty)
&& !currentEngineObject.SizeId.Equals( engineList.SizeId)) ////Use equals
{
engineList.SizeId = currentEngineObject.SizeId;
}

Related

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 )

Where function on list with multiple conditions returns errors

I'm trying to filter a list based on a few criteria and the .Where() function gives me an error in 2 parts of the same method.
if (string.IsNullOrWhiteSpace(champs))
{
data = dal.GetVueTache().Where(t =>
t.ProjetDescription64.ToLower().Contains(filtre.ToLower())
// *This Line || t.ProjetDescription256.ToLower().Contains(filtre.ToLower())
|| t.Description256.ToLower().Contains(filtre.ToLower())
||t.ResponsableNomCourt.ToLower().Contains(filtre.ToLower())
|| t.PrioriteDesc.ToLower().Contains(filtre.ToLower())
).ToList();
}
If I use any of the previous conditions except the one on the nullable field alone I get a perfectly filtered list on that criteria, if I add an OR "||" then I get a System.NullReferenceException on the first criteria.
I also have a similar issue in another part of the same method
else
{
data = dal.GetVueTache().Where(t =>
t.GetType().GetProperty(champs).GetValue(t).ToString().ToLower().Contains(filtre.ToLower())
).ToList();
}
This one filters my list based on the criteria "filtre" on the property "champs". It works on every property but the second one, which is a nullable one. I understand that this is where the issue comes from, but I can't find a way to test if the property is null before evaluating it and work around this from inside the .Where() Method.
Any advice will be greatly appreciated!!
Edit :
Thanks to Ivan Stoev for his solution!
The correct syntax for testing the null value in the first case is:
|| (t.ProjetDescription256 != null && t.ProjetDescription256.ToLower().Contains(filtre.ToLower()))
In the second case:
(t.GetType().GetProperty(champs).GetValue(t) != null && t.GetType().GetProperty(champs).GetValue(t).ToString().ToLower().Contains(filtre.ToLower()))
Just do a null check either the old way:
|| (t.ProjetDescription256 != null && t.ProjetDescription256.ToLower().Contains(filtre.ToLower()))
or the C# 6 way (utilizing the null conditional operator):
|| t.ProjetDescription256?.ToLower().Contains(filtre.ToLower()) == true
Btw, you can greatly simplify similar checks and avoid such errors by writing a simple custom extension methods like this:
public static class StringExtensions
{
public static bool ContainsIgnoreCase(this string source, string target)
{
return source == null ? target == null : target != null && source.IndexOf(target, StringComparison.CurrentCultureIgnoreCase) >= 0;
}
}
so your snippet becomes simply:
data = dal.GetVueTache().Where(
t => t.ProjetDescription64.ContainsIgnoreCase(filtre)
|| t.ProjetDescription256.ContainsIgnoreCase(filtre)
|| t.Description256.ContainsIgnoreCase(filtre)
|| t.ResponsableNomCourt.ContainsIgnoreCase(filtre)
|| t.PrioriteDesc.ContainsIgnoreCase(filtre)
).ToList();

c# Object reference not set to an instance of an object

I'm trying to work out if something does not exist in the table. I'm telling it to see if the UserInfo contains information for user.
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
if (Character.Username == null || Character.Username.Length == 0)
{
//do stuff
}
But I get an error on the if statement.
Object reference not set to an instance of an object.
It seems that the db.UserInfoes.SingleOrDefault(a => a.Username == user) expression returned null because it didn't find any matching records that satisfy the filter criteria.
so:
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
if (Character == null || Character.Username == null || Character.Username.Length == 0)
{
//do stuff
}
You wrote in the comments that you know that db.UserInfoes.SingleOrDefault(a => a.Username == user) returned null. Hence, Character is null and you need to check this case separately:
if (Character == null || // this line is new
Character.Username == null ||
Character.Username.Length == 0)
{
//do stuff
}
Since you say the error occurs on the if statement, Character is null. You need to add a check for if (Character == null).
First you should check whether Character is null, then later you should check for remaining in Character.
if(Character != null)
{
if(Character.Username == null || Character.Username.Lenght == 0)
{
//Do Stuff
}
}
EDIT:
or simply you can check only the Character, like
if(Character == null)
{
//Do Stuff
}
If you are getting an error on the if statement, then it is likely that your search:-
UserInfo Character = db.UserInfoes.SingleOrDefault(a => a.Username == user);
Has not found any record matching where Username equals user. When that happens, the value of Character is null.
Your issue is that you are trying to call a property on something that doesn't exist. You need to perform a check to ensure that Character is not null before calling any of its members.
if ( Character != null )
{
// Can now safely call properties on the Character object
}
else
{
// Take the appropriate action for circumstances where we can't
// find a user by username
}
You need to add a test on Character to know if it's null. If that's the case, you'll have the exception you mentionned.
So just do this :
if(Character != null)
{
//Your code can now safely call the Properties/Methods/etcetc...
}

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.

Categories

Resources