Simplify conditional if statement c# - c#

I have an if statement that becoming a bit cumbersome. I want to know if there's a better way of going about multiple similar if statements such as combining into one or using a different conditional statement such as a while or do loop. Any suggestions are appreciated.
if (options.OpenCloseOverridesOptions != null && !options.OpenCloseOverridesOptions.AreEqual(OpenCloseOverridesOptions))
return false;
if (options.DeliveryOpenCloseOverridesOptions != null && !options.DeliveryOpenCloseOverridesOptions.AreEqual(DeliveryOpenCloseOverridesOptions))
return false;
if (options.PickupOpenCloseOverridesOptions != null && !options.PickupOpenCloseOverridesOptions.AreEqual(PickupOpenCloseOverridesOptions))
return false;
if (options.PickupServiceWindowOverridesOptions != null && !options.PickupServiceWindowOverridesOptions.AreEqual(PickupServiceWindowOverridesOptions))
return false;
if (options.DeliveryServiceWindowOverridesOptions != null && !options.DeliveryServiceWindowOverridesOptions.AreEqual(DeliveryServiceWindowOverridesOptions))
return false;
if (options.ServiceWindowOverridesOptions != null && !options.ServiceWindowOverridesOptions.AreEqual(ServiceWindowOverridesOptions))
return false;
if (options.LineItemsOptions != null && !options.LineItemsOptions.AreEqual(LineItemsOptions))
return false;
the rundown is I am basically checking if an object is null, if not use an extension method to determine if a similar object is equal. (I'm not overriding isEquals and getHashCode ). if the object is null I cannot call the areEquals extension method so that check is necessary.

If you want to return bool you can return the condition directly.
We can use another skill (De Morgan's laws) let! into the statement, that will reverse all logic, let the code more clear.
return
(options.OpenCloseOverridesOptions == null || options.OpenCloseOverridesOptions.AreEqual(OpenCloseOverridesOptions)) &&
(options.DeliveryOpenCloseOverridesOptions == null || options.DeliveryOpenCloseOverridesOptions.AreEqual(DeliveryOpenCloseOverridesOptions)) &&
(options.PickupOpenCloseOverridesOptions == null || options.PickupOpenCloseOverridesOptions.AreEqual(PickupOpenCloseOverridesOptions))&&
(options.PickupServiceWindowOverridesOptions == null || options.PickupServiceWindowOverridesOptions.AreEqual(PickupServiceWindowOverridesOptions) &&
(options.DeliveryServiceWindowOverridesOptions == null || options.DeliveryServiceWindowOverridesOptions.AreEqual(DeliveryServiceWindowOverridesOptions)&&
(options.ServiceWindowOverridesOptions == null || options.ServiceWindowOverridesOptions.AreEqual(ServiceWindowOverridesOptions)&&
(options.LineItemsOptions == null || options.LineItemsOptions.AreEqual(LineItemsOptions)

Try this:
if (options.OpenCloseOverridesOptions != null && !options.OpenCloseOverridesOptions?.AreEqual(OpenCloseOverridesOptions)
|| !options.DeliveryOpenCloseOverridesOptions?.AreEqual(DeliveryOpenCloseOverridesOptions)
|| !options.PickupOpenCloseOverridesOptions?.AreEqual(PickupOpenCloseOverridesOptions))
return false;

Use the safe-navigation operator that was introduced in C#6 and a single if statement with several conditions, e.g.:
if (options.OpenCloseOverridesOptions?.AreEqual(OpenCloseOverridesOptions) != true
|| options.DeliveryOpenCloseOverridesOptions?.AreEqual(DeliveryOpenCloseOverridesOptions) != true
|| options.PickupOpenCloseOverridesOptions?.AreEqual(PickupOpenCloseOverridesOptions) != true)
return false;

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 )

C# if statement with string.Contains() not working as expected

I am stuck on what I thought would be a really easy problem. I am trying to redirect a user to a different website if the UserAgent does not contain a series of strings. The part I can not figure out is that the if statement works fine if I use the code below. I am happy with the results with this but something tells me that it is not good practice to only have an else statement and perform nothing if the statement proves to be true.
string strUserAgent = Request.UserAgent.ToString().ToLower();
if (strUserAgent != null)
{
if (Request.Browser.IsMobileDevice == true ||
strUserAgent.Contains("iphone") ||
strUserAgent.Contains("blackberry") ||
strUserAgent.Contains("mobile") ||
strUserAgent.Contains("windows ce") ||
strUserAgent.Contains("opera mini") ||
strUserAgent.Contains("palm") ||
strUserAgent.Contains("android"))
{
// Is this normal practice to only have an else block?
}else
{
Response.Redirect(AppState["redirectBack"].ToString());
}
When I try the next block of code the script redirects the user no matter what the UserAgent string contains. Can someone explain why this might be happening?
string strUserAgent = Request.UserAgent.ToString().ToLower();
if (strUserAgent != null)
{
if (Request.Browser.IsMobileDevice != true ||
!strUserAgent.Contains("iphone") ||
!strUserAgent.Contains("blackberry") ||
!strUserAgent.Contains("mobile") ||
!strUserAgent.Contains("windows ce") ||
!strUserAgent.Contains("opera mini") ||
!strUserAgent.Contains("palm") ||
!strUserAgent.Contains("android"))
{
Response.Redirect(AppState["redirectBack"].ToString());
}
You need De Morgan's Law. When you inverted your condition, your ORs need to become ANDs
Invert your statement using ! ("not"):
if(!(conditions)) { }
This will avoid the need to use an empty code block and you can just drop the else.
Your second codeblock will redirect when you're not on a mobile device or when your useragent contains any of the following strings. It depends on your input and your environment.
Do note that it's a lot easier to create a collection of the possibilities and check if your useragent is in there:
if(new[] {"iphone", "somephone", "otherphone" }.Any(x => useragent.Contains(x))) {}
It will always be true that at least one of your conditions will not be true. For instance, if strUserAgent.Contains(iphone) will be false if strUserAgent.Contains("blackberry") is true.
You need to change your OR (||) operator to a logical AND (&&) operator.
if (strUserAgent != null)
{
if (Request.Browser.IsMobileDevice != true &&
!strUserAgent.Contains("iphone") &&
!strUserAgent.Contains("blackberry") &&
!strUserAgent.Contains("mobile") &&
!strUserAgent.Contains("windows ce") &&
!strUserAgent.Contains("opera mini") &&
!strUserAgent.Contains("palm") &&
!strUserAgent.Contains("android"))
{
Response.Redirect(AppState["redirectBack"].ToString());
}
Not an answer, just a suggestion. You can make your code cleaner with an extension method:
public static bool ContainsAnyOf(this string source, params string[] strings)
{
return strings.Any(x => source.Contains(x));
}
And now write
if (strUserAgent.ContainsAnyOf("iphone", "blackberry", "mobile", "windows ce", "opera mini", "palm", "android"))
{
//
}
You need to reverse the entire thing. Putting !A || !B is not the same as !(A||B). In the first one if its A then it's Not B so it's True. In the second one it's False.
if (!(Request.Browser.IsMobileDevice == true ||
strUserAgent.Contains("iphone") ||
strUserAgent.Contains("blackberry") ||
strUserAgent.Contains("mobile") ||
strUserAgent.Contains("windows ce") ||
strUserAgent.Contains("opera mini") ||
strUserAgent.Contains("palm") ||
strUserAgent.Contains("android")
) )
{
Response.Redirect(AppState["redirectBack"].ToString());
}
string strUserAgent = Request.UserAgent.ToString().ToLower();
if (strUserAgent != null)
{
if (!(Request.Browser.IsMobileDevice == true ||
strUserAgent.Contains("iphone") ||
strUserAgent.Contains("blackberry") ||
strUserAgent.Contains("mobile") ||
strUserAgent.Contains("windows ce") ||
strUserAgent.Contains("opera mini") ||
strUserAgent.Contains("palm") ||
strUserAgent.Contains("android")))
{
Response.Redirect(AppState["redirectBack"].ToString());
}

Using ternary operator to check if null - null reference is not the same as null

I am attempting to use the ternary operator to check if a value is null and return one expression or the other. What I'm experiencing when incorporating this into a LINQ expression is that the Transact-SQL translation of the LINQ expression attempts to do a "column = null" rather than a "column IS NULL". I have reason to believe that this is because I'm doing the following:
mappedColumnName == (myVar == null ? null : myOtherVar)
Since it translates the following to columnName IS NULL in Transact-SQL:
mappedColumnName == null
Does anyone have any experience with this? I'd very much like to get this to work.
The entire LINQ expression:
(from MenuItem in menuContext.Menus
where MenuItem.IsSysAdmin == (ClientID == 1 ? true : false)
&& MenuItem.IsActive == true
&& MenuItem.ParentMenuCode == (ActiveSubMenu==null?null:ActiveMenu)
&& MenuItem.ClientID == (UseClientMenu ? ClientID : 0)
&& MenuItem.EmployeeID == (UseEmployeeMenu ? EmployeeID : 0)
orderby MenuItem.SortOrder, MenuItem.MenuName
select MenuItem);
Why don't you use
mappedColumnName == (myVar == null ? DBNull.Value: myOtherVar)
instead?
I've never actually attempted to use ternary operators in linq although you could write it as:
(
(myVar == null && mappedColumnName == null ) ||
(myVar != null && mappedColumnNmae == myOtherVar)
)
try this
(from MenuItem in menuContext.Menus
where MenuItem.IsSysAdmin == ((ClientID == 1 )? true : false)
&& MenuItem.IsActive == true
&& MenuItem.ParentMenuCode == ( (ActiveSubMenu==null) ?null:ActiveMenu)
&& MenuItem.ClientID == (UseClientMenu ? ClientID : 0)
&& MenuItem.EmployeeID == (UseEmployeeMenu ? EmployeeID : 0)
orderby MenuItem.SortOrder, MenuItem.MenuName
select MenuItem);

Nully the null error

Is there a way to tell the program that i don't care if a class reference is null.
For example:
if (playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
Why is he searching for the playermove (that can be null) and give me a null exeption error? i really don't care if the ispunchactivated is true.
Thanks.
If you put your two conditions the other way around:
ispunchactivated /*== true*/ || playermove[i].name == "punch"
// this isn't necessary
then, if the first one is true, the second one won't be checked.
However, unless you know playermove[i] won't be null if ispunchactivated is false, you should really be making the null check too, otherwise you'll still get exceptions:
ispunchactivated ||
(playermove[i] != null && playermove[i].name == "punch")
You just check it for null first.
There are not shortcuts here.
if (playermove == null || playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
Try this,
if ((ispunchactivated == true) || (playermove[i] != null && playermove[i].name == "punch" ))
{
Do the punch;
}
You can modify the if condition as follows:
if (ispunchactivated == true || (playermove!=null && playermove[i].name == "punch" ))
Just interchange the conditions and shortcircuitting will do that for you:
if (ispunchactivated == true || playermove[i].name == "punch")
{
Do the punch;
}
playermove[i] is only evaluated if ispunchactivated is false. That being said, you can still run into a null pointer exception if ispunchactivated is false and playermove[i] is null.
Change your condition as follows:
if(playermove !=null && playermove[i] != null)
{
if (playermove[i].name == "punch" || ispunchactivated == true)
{
Do the punch;
}
}

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