Better way to write if-else block [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I have following code (Sample code) which works very well.
I just think if there is any other better way we can write following code snippet more accurately with less code.
if(language == "English")
{
if(Student_id == 0)
{
someFunction();
}
else
{
if(getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)
{
someFunction();
}
}
}
Also, please note if Student_id is 0, getMarks(Student_id) throws error

(For more a complex scenario, check out this)
What I suggest for your case is:
To write it with less nested if-else block
one way to do it is by inverting the conditions and
gives early return whenever possible
To combine conditions with the same actions (in your case being the someFunction)
To exploit the Short Circuit Evaluation which is implemented in C# (also implemented in many other programming languages - as noted by Martheen in his comment).
if(language != "English")
return; //assuming nothing below
if(Student_id == 0 || getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)
someFunction(); //if someFunction is identical, this can be done
If you have other languages to be checked or if you have something to be done independent from your actions based on language == "English", however, then you should not return in the if (language != "English") statement:
if(language == "English") {
if(Student_id == 0 || getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)
someFunction(); //if someFunction is identical, this can be done
}
//Something else which must be done
Edit (after the question is edited):
For the additional condition, you can simply put it right after the Student_id == 0 because C# will always evaluate the left most if condition first (for its || short circuit evaluation).
To illustrate: for your case, this is ok:
if(Student_id == 0 || getMarks(Student_id) > 50){
//if Student_id == 0 is true, then getMarks(Student_id) wouldn't get evaluated
}
But this is not ok:
if(getMarks(Student_id) > 50 || Student_id == 0){
//if Student_id is 0, then getMarks(Student_id) would throw exception before Student_id == 0 is evaluated
}

In terms of readability, it sometimes helps to give your conditions readable names:
var languageIsEnglish = language == "English";
var studentIdIsNotSet = Student_id == 0;
var hasMoreThanOneSubject = subjectCount > 1;
var hasProjects = projectCount > 0;
if(languageIsEnglish && (studentIdIsNotSet || (hasMoreThanOneSubject || hasProjects )))
{
someFunction();
}

This might work;
if(language == "English" && (Student_id == 0 || getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0))
{
someFunction();
}

if(language == "English")
{
if(Student_id == 0 || getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)
{
someFunction();
}
}
Your else block doesn't offer any alternative and in fact calls the same function. In that case there is no need for another if block.

If there is no else for the 1st if I think you can write it in one line like this
if(language == "English" && (Student_id == 0 || (getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)))
someFunction();
if there is an else you can do it like this
if(language == "English")
{
if(Student_id == 0 || getMarks(Student_id) > 50 || subjectCount > 1 || projectCount > 0)
someFunction();
}
else
{
}

Related

Linq opening and closing parentheses does not match

I have this code:
using (Entities db = new Entities())
{
refer = db.Refferals.Where(r =>
r.RefferalDetails.Any(rd =>
(Name.Contains(rd.Name) || rd.Name.Contains(Name) || LastName.Contains(rd.LastName) || rd.LastName.Contains(LastName)
|| Company.Contains(r.Company) || r.Company.Contains(Company)
Mobile.Contains(rd.Mobile) || rd.Mobile.Contains(Mobile))) &&
Mobile.Length > 9 && Name.Length > 1 && LastName.Length > 1 && Company.Length > 2
).ToArray();
}
Although the parentheses count is correct but the editor offers that there is one extra parantheses.
I tried restarting Visual Studio but its the same.
Try adding the missing || between r.Company.Contains(Company) and Mobile.Contains(rd.Mobile).
And fix the indenting, that makes it much easier to see what's wrong. When I indented it, the missing operator stuck out like a sore thumb, and it's easy to see how the parens work.
using (Entities db = new Entities())
{
refer = db.Refferals.Where(r =>
r.RefferalDetails.Any(rd =>
(
Name.Contains(rd.Name)
|| rd.Name.Contains(Name)
|| LastName.Contains(rd.LastName)
|| rd.LastName.Contains(LastName)
|| Company.Contains(r.Company)
|| r.Company.Contains(Company)
|| /* <-- ADDED OR OPERATOR HERE */
Mobile.Contains(rd.Mobile)
|| rd.Mobile.Contains(Mobile)
)
)
&& Mobile.Length > 9
&& Name.Length > 1
&& LastName.Length > 1
&& Company.Length > 2
).ToArray();
}
It's missing one**||** before Mobile.Contains(rd.Mobile)
refer = db.Refferals.Where
(
r => r.RefferalDetails.Any
(
rd =>
(
Name.Contains(rd.Name) || rd.Name.Contains(Name) || LastName.Contains(rd.LastName) || rd.LastName.Contains(LastName)
|| Company.Contains(r.Company) || r.Company.Contains(Company)
|| Mobile.Contains(rd.Mobile) || rd.Mobile.Contains(Mobile)
)
)
&& Mobile.Length > 9 && Name.Length > 1 && LastName.Length > 1 && Company.Length > 2
).ToArray();
Without running code it seems you do some kind of unary selections (rd). I would suggest you start refactoring your code and break out each condition a part...

Not understanding LINQ query

I am maintaining a project and have come across some code which I can't understand. LINQ query:
var toDraw = from tile in testArr.AsEnumerable()
where tile.Item_Business_Unit != null ?
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) ||
(tile.Sales_Code.ToString() == cpg)) && (tile.Unit_Price != 0)) :
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) ||
(tile.Sales_Code.ToString() == cpg)) && (tile.Unit_Price != 0))
select tile;
From what I understand, from an array a tile is being selected which has the following criteria:
Ending date can be datetime.now or datetime.minvalue
Sales code can be null or can be equal to customer no or cpg
Unit price should be greater than 0
But I am not understanding why there is a conditional expression after tile.Item_Business_Unit since both of the conditions perform the same thing. So will the item be selected even if it has a null business unit? And does this work different from normal if/else operations?
Any suggestions would be very appreciated.
Are you being thrown by the shortcut notation?
x = (test_case) ? (true_part) : (false_part);
If test_case evaluates to true, you would have
Whereas if test_case evaluates to false, this expression would be evaluated
UPDATE:
As an FYI: The resulting test of both sides of that conditional expression above are equal, so that cryptic code is not even necessary.
You could replace that with this:
var toDraw = from tile in testArr.AsEnumerable()
where
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) || (tile.Sales_Code.ToString() == cpg)) &&
(tile.Unit_Price != 0))
select tile;

conditional where [duplicate]

This question already has an answer here:
Conditional WHERE in LINQ
(1 answer)
Closed 9 years ago.
I need to write a conditional query in linq:
if field.val1 == 0:
var q = from field in cw.fields
select field
if field.val1 != 0 and field.val2 == 0:
var q = from field in cw.fields
where field.val1 == 1
select field
if field.val1 != 0 and field.val2 != 0:
var q = from field in cw.fields
where field.val1 == 1 and field.val2 == 1
select field
How can I do this?
Because your condition depends on the values your querying, you have to just extend your where clause with additional cases using ||:
var q = from field in cw.fields
where
(field.val1 == 0) ||
(field.val1 != 0 and field.val2 == 0 && field.val1 == 1) ||
(field.val1 != 0 and field.val2 != 0 && field.val1 == 1 and field.val2 == 1)
select field
#MarcinJuraszek's answer will work but let me give a different perspective.
First of all, ditch the sql style syntax. It gets in the way, obscures what is actually going on and is generally just a feel-good abstraction rather than one that will result in more communicative code. Let's rewrite things using lambda syntax
IEnumerable<string> getFields(SomeField field, YourDatabase cw) {
if(field.val1 == 0:)
return cw.fields.ToList();
if(field.val1 != 0 and field.val2 == 0)
return cw.fields.Where(f => f.val1 ==1).ToList();
if(field.val1 != 0 and field.val2 != 0)
return cw.fields.Where(f => f.val1 == 1 and f.val2 == 1).ToList();
}
note that the only way things differ is the lambda, and a lambda is an object, in this case, an Expression object! So you can use a very standard abstract factory pattern here
return cw.fields.Where(matchingCondition(field)).ToList();
//elsewhere...
Expression<Func<SomeField, bool>> matchingCondition(SomeField field) {
if(field.val1 == 0:) return f => true;
if(field.val1 != 0 and field.val2 == 0) return f => f.val1 == 1
if(field.val1 != 0 and field.val2 != 0) return f => f.val1 == 1 and f.val2 == 1;
throw new InvalidOperationException("No match to condition");
}

Why is my query not returning anything

I was writing a LINQ query to filter the records based on user input and selection. Some of the inputs may not be given from the user. So i need to filter based on the given input. I tried giving value for only 1 out of 5 optional inputs. But the query is not returning anything. Please help me to find the proper query. you can better understand after seeing the query.
Code
var model = (from items in Db.Items
where ((items.ItemNo == null ||
items.ItemNo == String.Empty) ||
((items.ItemNo.CompareTo(DD.FromItemNo) >= 0) &&
(items.ItemNo.CompareTo(DD.ToItemNo) <= 0))) &&
(items.InfoTypeId == 0 ||
(items.InfoTypeId == DD.InfoType)) &&
(items.CreatedOn == null ||
(items.CreatedOn >= DD.Start &&
items.CreatedOn <= DD.End)) &&
(items.StatusId == 0 ||
(items.StatusId == DD.Status)) &&
(items.LocationId == 0 ||
(items.LocationId == DD.Location)) &&
(items.CollectionId == 0 ||
(items.CollectionId == DD.Collection))
select new ViewModel()
{
Itemid = items.Id,
INo = items.ItemNo,
BTags = (from asd in Db.BibContents
where asd.BibId == items.BibId &&
asd.TagNo == "245" &&
asd.Sfld == "a"
select asd.Value).FirstOrDefault(),
Sid = (from stat in Db.ItemStatus1
where stat.Id == items.StatusId
select stat.Description).FirstOrDefault(),
Option = DD.Option,
CurrItemNo = DD.ItemNumber
}).ToList();
You've got to check the values of DD for nulls or 0s, not those of items:
var model = (from items in Db.Items
where
(
(DD.ItemNo == null || DD.ItemNo == String.Empty)
|| (items.ItemNo.CompareTo(DD.FromItemNo) >= 0 && items.ItemNo.CompareTo(DD.ToItemNo) <= 0)
)
&& (DD.InfoTypeId == 0 || (items.InfoTypeId == DD.InfoType))
&& (DD.CreatedOn == null || (items.CreatedOn >= DD.Start && items.CreatedOn <= DD.End))
&& (DD.StatusId == 0 || (items.StatusId == DD.Status))
&& (DD.LocationId == 0 || (items.LocationId == DD.Location))
&& (DD.CollectionId == 0 || (items.CollectionId == DD.Collection))
select ...

Entity framework strings using greater than operator

How do I make this query work like it does in sql? In sql I can use < and > operators on strings.
I've been googling this for about 20 minutes and have found no solution yet.
I cannot convert r.ExemptionCode to an integer as it may have values like '91A,9AA,ZZZ,Z01'
from r in results
where (r.ExemptionCode > "900" || r.ExemptionCode == "701" || r.ExemptionCode == "702" || r.ExemptionCode == "721" || r.ExemptionCode == "724")
select r
Try this :
from r in results
where (r.ExemptionCode.CompareTo("900") > 0 || r.ExemptionCode == "701" || r.ExemptionCode == "702" || r.ExemptionCode == "721" || r.ExemptionCode == "724")
select r

Categories

Resources