Related
I have a rather large Flag enum called AmendmentType. I need to check to see that if it has specific Enums and any others.
For Example:
var foo = AmendmentType.Item1;
if (foo.HasFlag(AmendmentType.Item1) && (ANYTHING ELSE))
{
//DO NOT ALLOW
}
else if (foo.HasFlag(AmendmentType.Item2) && foo.HasFlag(AmendmentType.Item6))
{
//DO NOT ALLOW
}
else
{
//ALLOW
}
How would this be possible? There are about 20 different items in the Flag Enum and it seems like there should be an easier way than checking all possible combinations.
If you're only interested in the part you've labeled as "anything else", you can use:
if (foo.HasFlag(AmendmentTypeEnum.Item1) && (foo & ~AmendmentTypeEnum.Item1) != 0)
Or just check that it isn't exactly equal to Item1:
if (foo.HasFlag(AmendmentTypeEnum.Item1) && foo != AmendmentTypeEnum.Item1)
Note that checking for the presence of all of multiple flags only needs a single HasFlag call too:
else if (foo.HasFlag(AmendmentTypeEnum.Item2 | AmendmentTypeEnum.Item6))
(I'd also suggest removing the Enum suffix - it'll be a lot easier to read the code without it :)
Another option would be to set up flags that signify the combinations you're interested in.
var flagComboA = AmendmentTypeEnum.Item1;
var flagComboB = AmendmentTypeEnum.Item2 | AmendmentTypeEnum.Item6;
if(foo == flagComboA || foo == flagComboB)
{
//DO NOT ALLOW
}
if(string s; s = Console.ReadLine(); s == "ja" || "Ja")
A screenshot of all the errors i got from that single line
I dont understand a single of them
Can somebody explain
You cannot declare a variable inside of if statement, and this is also invalid: s == "ja" || "Ja" you need to separate each condition like this:
string s = Console.ReadLine();
if(s == "ja" || s == "Ja")
Or you can just use:
if(s.ToLower() == "ja")
string s;
s = Console.ReadLine();
if(s == "ja" || s== "Ja")
{
}
?
This is not a valid C# syntax. Inside if statement there should be an evaluation that results in a boolean value. Can't declare new variables inside, nor s == "ja" || "Ja" makes any sense.
C# does not allow that sort of thing. Try something like the following:
string s = Console.ReadLine() ;
bool isEndOfFile = s == null ; // Console.ReadLine() returns null at end-of-file
if ( isEndOfFile ) throw new Exception( "That was unexpected!" ) ;
bool isYes = !isEndOfFile && s.Trim().Equals( "Ja" , StringComparison.CurrentCultureIgnoreCase ) ;
if ( isYes )
{
HandleYesInput() ;
}
In general, keep things simple. Intentional programming will help you: work in a declarative manner to express your intent using small discrete methods and local variables as flags for each of the conditions you're testing, rather than trying to do everything in one complicated expression. You could do something like this:
string s = null ;
if ( (s=Console.ReadLine()) && s != null && s.Trim().Equals("Ja",StringComparison.CurrentCulture.IgnoreCase) )
{
...
}
You gain a little brevity at the expense of readability, traceability and debugability. When your code doesn't work as expected, which version do you think will be easier to understand or to diagnose and fix? That goes triple, if the person who's assigned the task of fixing the problem doesn't understand the code or what it's trying to accomplish and has to get up to speed quickly.
And that person might well be you, looking at code your wrote 5 years earlier.
I have three if statements which they are apparently working on different functions. I wanted to combine them into one function, thus I have to combine the if statement. But I was stuck at how to use the || && and ().
My functions as filters, user can fill in whichever textboxes. On button click event, the code will find those that met criteria. Three of them work well independently, but combining them is very tough. Please bear with me and help me, I am just a very new programmer and no background at all. I am stuck for days. ;(
My filters snapshot:
First:
if (itemAuthor.ToLower() == txtComAuthor.Text.ToString().ToLower())
Second:
if ((!DateTime.TryParseExact(txtComStartDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out startDate)
|| DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) >= startDate) &&
(!DateTime.TryParseExact(txtComEndDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out endDate)
|| DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) <= endDate))
Third:
if (txtComKeyword1.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword1.Text.ToLower()) ||
txtComKeyword2.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword2.Text.ToLower()) ||
txtComKeyword3.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword3.Text.ToLower()) ||
txtComKeyword4.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword4.Text.ToLower()))
Whether to use || or && depends on whether you want the meaning at least one condition is true (use ||) or all conditions must be true (use &&).
If you need to mix both meanings, use () to cause conditions to be evaluated against each other, e.g.
if ( (a && b) || (c && d))
means if both a and b are true or both c and d are true.
It makes for easier-to-read and maintain code if you define separate booleans for each portion of the compound logic. There is no performance difference.
bool condition1 = !DateTime.TryParseExact(txtComStartDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out startDate);
bool condition2 = DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) >= startDate);
bool condition3 = !DateTime.TryParseExact(txtComEndDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out endDate);
bool condition4 = DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) <= endDate);
if ((condition1
|| condition2 &&
(condition3
|| condition4)
It will help you understand if you break each one of these clauses into functions and divvy up the complexity accordingly. Smaller pieces are easier to work with, and more maintainable in the long run. When you evolve as a programmer, you will eventually not use if statements for this at all, but rather leverage the power of polymorphism.
For now, begin by piecing things apart.
public void btnAnalyze_onClick(){
List<Item> results = new ArrayList<Item>();
if(txtComAuthor.Text != String.Empty)
{
List<Item> matched = filterByAuthor(txtComAuthor.Text);
results.addRange(matched);
}
if(txtComStartDate.Text != String.Empty)
{
List<Item> matched = filterByStartDate(txtComStartDate.Text);
results.addRange(matched);
}
// do the same for the others
return results;
}
public List<Item> filterByAuthor(String desiredAuthorName){
List<Item> matches = new ArrayList<Item>();
//have your data access piece here, from DB/Excel/whatever.
List<Item> candidates = ...
foreach(Item candidate in candidates){
if(candidate.ToLower() == desiredAuthorName){
matches.add(candidate)
}
}
return matches;
}
Experienced programmers will realize that there's a lot of duplication here and will have fits at the violations of DRY and performance. That's ok. It can be refactored. For a novice, this will be the easiest style to understand.
If you follow this style, it should be readily apparent where you need to do the filtering. Basically, you will need to replace the if statement in the foreach loop with the condition for the text field you're thinking about.
But you shouldn't need to add a bunch of clauses together doing this because you've broken things apart a little better. If you still find you need a few nested ifs, break it down further into even smaller functions.
When in doubt about logical grouping, put parentheses around every pair of operations. That way you know how the pairs will be combined.
if ((A && B) || (C && D)) will evaluate the (A && B) and (C && D) segments, then "or" those intermediate results together to produce the final value.
For further reading, search for commutative, associative, and distributive properties of boolean logic.
As far as I can tell, you want to evaluate all 3 at the same time, but simply adding them into one big line will be hard to read or maintain. I'd recommend setting seperate bool values for each of your previous ifs:
bool firstIf = (itemAuthor.ToLower() == txtComAuthor.Text.ToString().ToLower());
Then comparing all 3 in one statement:
if (firstIf && secondIf && thirdif)
{
Console.WriteLine("It works!");
}
This way, it is easier to make changes later if need be, and you can still read the code.
I have a function that calls a lot of other functions from different objects. Each function has to return true before calling the next one. As you can see I am using too many if statements. How can I improve the code and make it neater? Thanks
bool ISOKToDoSomthing()
{
boo retVal = false;
retVal = ObjA.CheckVersion(oldVersion);
if(retVal)
{
retVal = objB.CheckUserRight();
}
if(retVal)
{
retVal = ObjC.ISDBExist();
}
if(retVal)
{
retVal = OjbD.ISServerUp(ServerName);
}
//tons of similar code as above
.........
return retVal;
}
return
ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
My advice: do nothing to this code without a clear business case for making the change.
Your code is clear, obvious, likely correct, easy to maintain and easy to debug. Why on earth would you want to change it in any way? Spend your time adding value by fixing bugs and adding features, not by changing working code unnecessarily. When your boss asks you "so what did you do today?" the answer should not be "I increased our schedule risk to by making unnecessary cosmetic changes to correct, working, already-debugged code".
Now, if there really is a problem here, the problem is likely not that the code is hard to read, but rather that the code rigidly encodes what ought to be a user-configurable business process. In that case, create an object called "Workflow" that encodes the business process, and an engine which evaluates an arbitrary workflow. Then construct an instance of that object that represents the desired workflow based on input from the user.
That actually adds value for the user; the user cares not a bit whether you use nested "if" statements or not.
if (!ObjA.CheckVersion(oldVersion)) return false;
if (!ObjB.CheckUserRight()) return false;
if (!ObjC.IsDBExist()) return false;
if (!ObjD.IsServerUp(serverName)) return false;
... your other checks ...
return true;
The short-circuiting of && is useful for a few conditions, but if you have "tons" of them, IMO that's way too much to try and stick in one statement.
A combination of the two might be useful, though. More useful still would be to condense some of these checks together into bigger chunks (but smaller than IsOKToDoSomething). For instance, check whether you have access to the database (whether it exists, whether you can log in to it, etc) all at once
Truth be told, the fact that you have so many objects to check hints at a design issue -- namely, you're trying to do too much at once, or you have a "god object" somewhere that has its little tentacles in every aspect of the system. You might want to look at fixing that.
return ObjA.CheckVersion(oldVersion) && objB.CheckUserRight() && ObjC.ISDBExist() && OjbD.ISServerUp(ServerName)
The && operator will short-circuit, so you can chain them like so:
bool ISOKToDoSomthing()
{
return
ObjA.CheckVersion(string oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName) &&
//tons of similar code as above
.........
}
bool ISOKToDoSomthing()
{
return ObjA.CheckVersion(string oldVersion) &&
ObjB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
}
Perhaps?
retVal = objB.CheckUserRight() && ObjC.ISDBExist() && OjbD.ISServerUp(ServerName);
etc.
A side note, you can test for example, if objB is null before calling a method on it in one statement (the code will break execution as soon as a condition has not been met, i.e. won't call the next condition) so you don't need lots of if(objB != null) type statements. E.g.:
retVal = (objB != null && objB.CheckUserRight()) && (ObjC != null && ObjC.ISDBExist()) && (OjbD != null && OjbD.ISServerUp(ServerName));
You can leverage the fact that C# does short-circuit evaluation:
return
ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
Editing to fix syntax on CheckVersion's parameters
How about using and:
retVal = ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
return retval;
To make the code less wordy, you could try a while loop. Given that your method here is to not ever change the value of your original value if it /ever/ turns false, then it would be while(retval) {} and iterate over a list of actions. Personally, I think this is ugly. Consider using a switch, or even (yuck on this, but it would work) a bitwise enum.
From my perspective, when I see myself writing code like this, I've made a grave architectural mistake somewhere and I should really rethink the reason behind making this call. Perhaps you should take another look at your logic, rather than just your code. Sit down and draw some boxes and work a bit more in the design phase and you might find yourself building things very differently.
edit: or yeah, like everyone else did, you can make your iteration a single if statement. Again, this is a bigger problem than a long list of booleans.
It depends on how much you want to change. Perhaps instead of returning a bool from your sub-methods, you could throw an exception.
bool retVal = true;
try
{
ObjA.CheckVersion(oldVersion);
objB.CheckUserRight();
ObjC.ISDBExist();
OjbD.ISServerUp(ServerName);
}
catch (SomeException ex)
{
// Log ex here.
retVal = false;
}
return retVal;
If you do something like this, IsDBExist probably isn't the best name (since Is generally translates to "returns a bool" in my mind), but you get the picture.
At some time there will be a large amount of records, about 50,000.
with that in mind is the method GetEquipmentRecord up to the task.
thanks for you opinions.
c# ,net 2,0
public enum EquipShift { day, night };
public class EquipStatusList : List<EquipStatus>
{
string SerialFormat = "yyyyMMdd";
int _EquipmentID;
string _DateSerial;
EquipShift _Shift;
public EquipStatus GetEquipmentRecord(int equipmentID, EquipShift shift,
DateTime date)
{
_DateSerial = date.ToString(SerialFormat);
_Shift = shift;
_EquipmentID = equipmentID;
return this.Find(checkforEquipRecord);
}
bool checkforEquipRecord(EquipStatus equip)
{
if ((equip.EquipmentID == _EquipmentID)
&& (equip.Shift == _Shift)
&& (equip.Date.ToString(SerialFormat) == _DateSerial))
return true;
else
return false;
}
}
update :
I have changed the evaluation to read
if ((equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift) )
not sure it that helps
Without commenting on your choice of algorithm, we can say that it probably is optimized enough.
You've got an O(n) find() in there; searching a sorted list with a binary search would be O(lg n) and searching a hash-set (or Dictionary in C# 2.0) would be O(1) for example. Hash-set would obviously be the way to go if you were calling this function often.
But bottlenecks are rarely where you expect them, so that you ask the question on this particular instance means that, on balance, profiling later will actually show that the big slowdowns are elsewhere.
You could speed this up considerably by implementing a suitable GetHashCode method and using a System.Collections.Generic.HashSet<EquipStatus> as the backing container. However, as it's not entirely clear how you are using your class (i.e. which other List<T> methods you use), ymmv.
No, it is not. Your whole construct is not able to be used in a multitasking environment. You are storing the details to search for as instance members of the class. I would take advantage of PLINQ (Parallel Linq) and the usual operators, also I wouldn't derive from the List itself, but offer an extension method like this:
public static EquipStatus GetEquipmentRecord(this IEnumerable<EquipStatus> list, int equipmentID, EquipShift shift, DateTime date)
{
return list.AsParallel().FirstOrDefault(e => e.EquipmentID == equipmentID && e.Shift == shift, e.Date.Date == date.Date);
}
By this, multiple searches at the same time are possible.
well an obvious way to improve your checkForEquipRecord method is to change
if ((equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift) )
return true;
else
return false;
to just return (equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift)
As far as efficiency goes, it might already be an optimization that the JIT compiler makes.