Optimizing "this" type of loop - c#

I'm currently (and have in the past been) using this loop to look through an array of custom classes and make sure that a boolean member value of each class in the array is equal. Is there a better (more efficient, simpler to code perhaps) way to do this?
Since that explanation is pretty bad and for lack of a better way to explain it, I'll simply ask, "Is there a better way to optimize 'this' loop?"
//set to true so the loop runs
boolean AllArentEqual = true;
while (AllArentEqual){
//do some stuff to make stuff equal
///// Check if stuff is equal /////
//set to false to determine later
AllArentEqual = false;
//check if any aren't equal
for (int i = 1; i < anArrayOfClass.length; i++){
if (anArrayOfClass[i - 1].BooleanValue != anArrayOfClass[i].BooleanValue){
//one isn't equal so set the loop to be re-run
AllArentEqual = true;
}
}
} //loop until stuff is equal

An obvious minor improvement is the addition of a break:
for (int i = 1; i < anArrayOfClass.length; i++){
if (anArrayOfClass[i - 1].BooleanValue != anArrayOfClass[i].BooleanValue){
//one isn't equal so set the loop to be re-run
AllArentEqual = true;
break; // We're done in this round
}
}
Once it is established that not all are equal, there's no point in checking further.

I would rework this a bit by extracting a method, and then potentially doing something like:
AttemptMakeEqual(anArrayOfClass);
while (anArrayOfClass.Any(c => c.BooleanValue != anArrayOfClass[0].BooleanValue))
{
AttemptMakeEqual(anArrayOfClass);
}
// Extract out a method to:
void AttemptMakeEqual(YourClass[] values)
{
//do some stuff to make stuff equal
}
If there is a chance you may have "all equal" values, and you don't always need to run the operation first (ie: your new version), you could just do:
while (anArrayOfClass.Any(c => c.BooleanValue != anArrayOfClass[0].BooleanValue))
{
//do some stuff to make stuff equal
}

I'd maybe do something like this:
class Widget
{
public Widget( bool truthiness )
{
this.Truthiness = truthiness ;
}
public bool Truthiness { get ; private set ; }
}
class FooBar
{
private Widget[] Widgets { get ; private set; }
private Widget[] GetSomeWidgets()
{
throw new NotImplementedException() ;
}
public FooBar()
{
Widgets = GetSomeWidgets() ;
}
private void WorkOnWidgets()
{
throw new NotImplementedException() ;
}
public void MakeEqual()
{
bool areEqual ; // zero or one widget and it's not a problem
while ( !(areEqual=CheckIfAllWidgetsEqual()) )
{
WorkOnWidgets() ;
}
return ;
}
public bool CheckIfAllWidgetsEqual()
{
bool value = true ;
if ( Widgets.Length > 1 )
{
Widget first = Widgets[0] ;
Widget firstUnequal = Widgets.Skip(1).FirstOrDefault( x => x.Truthiness != first.Truthiness ) ;
value = firstUnequal != null ;
}
return value ;
}
}

Related

Looking to check for one's or zeros in a Bitstring

Does anyone have an idea how to check for one's or zeros in a Bitstring? The below code checks for ones and zeros in a string, but I would like to add an extension bitstring that does the same thing. This way, I can use the method on the bitstring itself with out having to first evaluate the string.
Currently, I have to check before I entered the bitstring method.
string MustBeBitsInStringOnesOrZeros = "11001";
bool boTesting = Is1Or0(MustBeBitsInStringOnesOrZeros);
// I would like to add an extension to check for ones and zeros
// Example: MustBeBitsInStringOnesOrZeros.Is1Or0();
if (boTesting == true)
{
Bitstring a = new Bitstring(MustBeBitsInStringOnesOrZeros);
}
else
{
string b = MustBeBitsInStringOnesOrZeros;
}
private static bool Is1Or0(string stringBit)
{
// This function check each
// character in a string for "1"
// or "0".
bool results = false;
for (int i = 0; i < stringBit.Length; i++)
{
var x = stringBit[i];
if (x == '1' || x == '0')
{
results = true;
}
else
{
results = false;
break;
}
}
return results;
}
===
Modified to show results of Bassie's example from a sealed class.
Bassie,
Well, what I was trying to say was that I cannot place the method in the sealed class with the keyword 'this' in the method. So I created another class but, I have to use it a different way and I wanted to use it the way you call it.
//I have to use it this way:
Bitstring OnesAndZeroCheck = new Bitstring(); // Bitstring is in a sealed class
Boolean g = OnesAndZeroCheck.IsBitstring2("1100111100011100101010101010101101010101010"); // Is in the sealed class
//but want to call it this way:
var successInput = "1101";
successInput.Is1Or0(); // true
If I understand you correctly, you could define your extension method like this
public static class StringExtensions
{
public static bool Is1Or0(this string stringBit)
=> stringBit.All(c => c == '1' || c == '0');
}
And call with
var successInput = "1101";
successInput.Is1Or0(); // true
var failureInput = "1121"
failureInput.Is1Or0(); // false
From MSDN Enumerable.All:
Determines whether all elements of a sequence satisfy a condition.
This works because a string is actually just an IEnumerable of char - so when we call the IEnumerable.All() extension method, we check the condition against each individual char in the string
Note you will need to include using System.Linq; to your file that contains the extension method
tested in video.
https://youtu.be/CgMFYctc3Ak
public static bool isBitstring(string s)
{
foreach (char c in s)
{
if (!(c >= '0' && c <= '1')) {
return false;
}
}
return true;
}
string str = "100000011100101010010101";
if (isBitstring(str))
{
Console.WriteLine("is Bitstring");
}
else
{
Console.WriteLine("is not Bitstring");
}

WPF: Equals(Control.background, SolidColorBrush) constantly false

I have a List<SolidColorBrush> lColorBrushes and want to compare the Background of some Buttons with it's content. The Buttons are saved in List<Button> lClickedButtons.
foreach (var oBtn in lClickedButtons)
{
for (var i = 0; i < lColorBrushes.Count; i++)
{
if (Equals(oBtn.Background, lColorBrushes[i]))
{
//oBtn gets cool stuff
}
}
}
I did the exact same thing earlier and it worked tottaly fine. But for whatever reason (I dont see any difference to earlier circumstances of my Code) now the if condition is constantly false. Also if for example oBtn.Background and lColorBrushes[i] both are #FFFF0000.
The reason for Equals() returning false, is that these are two entirely different references, that just happen to have the same Color property.
If you want to compare the two SolidColorBrushes, I suggest you use the IEqualityComparer interface, as such: (source).
public class SolidColorBrushComparer : IEqualityComparer<SolidColorBrush>
{
public bool Equals(SolidColorBrush x, SolidColorBrush y)
{
// If you do not care about opacity, disregard it.
return x.Color == y.Color &&
x.Opacity == y.Opacity;
}
public int GetHashCode(SolidColorBrush obj)
{
return new { C = obj.Color, O = obj.Opacity }.GetHashCode();
}
}
Then, you can use it inside your loop as follows:
foreach (var oBtn in lClickedButtons)
{
for (var i = 0; i < lColorBrushes.Count; i++)
{
if (new SoldiColorBrushComparer().Equals(oBtn.Background, lColorBrushes[i]))
{
//oBtn gets cool stuff
}
}
}

Most efficient way of evaluating independent variable for a similar outcome

I am doing a project using Unity and C# but I don't feel this is necessarily Unity related. I have two separate hands that are represented by 2 instances of a hand class.
public class HandController
{//....class}
HandController LeftHand = new HandController();
HandController RightHand = new HandController();
I am constantly doing twice the work in a lot of areas to affect the hands because each hand needs to be treated independently. So for instance I am using a Leap motion controller and if one of the hands is not detected I want to inform the user of this. So I change the color of the hand in the update method.
Color notDetected = Color.red;
Color detected = new Color(189/255.0f, 165/255.0f, 134/255.0f);
if (!LeftHandTracked)
LeftHand.renderer.material.color = notDetected;
if (!RightHandTracked)
RightHand.renderer.material.color = notDetected;
if (LeftHandTracked)
LeftHand.renderer.material.color = detected;
if (RightHandTracked)
RightHand.renderer.material.color = detected;
Is there a more efficient way of doing this? I hate having duplicate if conditionals sprawled all over my code. I also am tracking fingers, so each finger needs to be recognized and I get an even worse chain of if conditionals
if (TappedFingers[0] && !_keySpamBlock)
LeftHand.SetSide(true, _pointer);
if (TappedFingers[1] && !_keySpamBlock)
LeftHand.SetSide(true, _middle);
if (TappedFingers[2] && !_keySpamBlock)
LeftHand.SetSide(true, _ring);
if (TappedFingers[3] && !_keySpamBlock)
LeftHand.SetSide(true, _pinky);
if (TappedFingers[4] && !_keySpamBlock)
RightHand.SetSide(true, _pointer);
if (TappedFingers[5] && !_keySpamBlock)
RightHand.SetSide(true, _middle);
if (TappedFingers[6] && !_keySpamBlock)
RightHand.SetSide(true, _ring);
if (TappedFingers[7] && !_keySpamBlock)
RightHand.SetSide(true, _pinky);
_pinky and _ middle and etc.. are hash values I pass into SetSide method in the HandController class that allow me to access the animationcontroller booleans I have set in Unity. SetSide() basically just sends the true if a user taps their finger and it plays an animation on the appropriate finger.
EDIT: To Clarify a little more whats going on
I am connecting to an API by inheriting a class and establishing an event listener:
public class AppListener : ErghisListener {
public delegate void onUpdate(Data d);
public event onUpdate Updated;
public override void OnErghisFrame(Data data)
{
Loom.QueueOnMainThread(() => { this.Updated(data); });
}
}
Then I have a MainController where recieve the data object from the API:
public class MainController: MonoBehaviour{
private AppListener _appListener;
private int _pointer;
private int _middle;
private int _ring;
private int _pinky;
void Start()
{
this._appListener = new AppListener();
this._appListener.Updated += callback;
this._pointer = Animator.StringToHash("Pointer");
this._middle = Animator.StringToHash("Middle");
this._ring = Animator.StringToHash("Ring");
this._pinky = Animator.StringToHash("Pinky");
}
public void callback(Data d)
{
// Here is where all my annoying if conditionals were.
bool[] TappedFingers = d.tappedF;
}
Your first code snippet would look much more logical if it was something like this:
class HandController : MonoBehaviour
{
bool m_Tracked;
Color NotDetected { get { return Color.red; } }
Color Detected { get { return new Color(189/255.0f, 165/255.0f, 134/255.0f); } }
public bool Tracked
{
if (m_Tracked == value) return;
m_Tracked = value;
renderer.material.color = value ? Detected : NotDetected;
}
}
// ...
LeftHand.Tracked = LeftHandTracked;
if (TappedFingers.Length != FINGERS*2)
{
Debug.LogError("Unexpected amount of fingers: " + TappedFingers.Length);
return;
}
for(int i = 0; i < FINGERS; i++)
{
LeftHand.SetSide(TappedFingers[i], i);
}
for(int i = FINGERS; i < FINGERS*2; i++)
{
RightHand.SetSide(TappedFingers[i], i-FINGERS);
}
You could simply use else here.
if (LeftHandTracked)
LeftHand.renderer.material.color = detected;
else
LeftHand.renderer.material.color = notDetected;
I would prefer inline conditional.
LeftHand.renderer.material.color = LeftHandTracked ? detected : notDetected;
As for the second example, you can wrap all the statements in a single if block to remove visual noise:
if (!_keySpamBlock)
{
if (TappedFingers[0])
LeftHand.SetSide(true, _pointer);
if (TappedFingers[1])
LeftHand.SetSide(true, _middle);
}
The other option with Linq (which is not more efficient, but so much prettier):
var sides = new[] { _pointer, _middle };
if (!_keySpamBlock)
TappedFingers.Zip(sides, (x, y) => { if (x) { LeftHand.SetSide(true, y); });
I'd say this is clear and looks good enough. I don't see how polymorphism could help here, but you could investigate it yourself.
for the first part:
LeftHand.renderer.material.color = LeftHandTracked ? detected : notDetected;
RightHand.renderer.material.color = RightHandTracked ? detected : notDetected;
second part:
if(!_keySpamBlock)
{
int index=Array.FindLastIndex(TappedFingers.Take(8).ToArray(), i => i);
switch (index)
{
case 0: {LeftHand.SetSide(true, _pointer); break;}
case 1: {LeftHand.SetSide(true, _middle); break;}
//.........
case 7: {RightHand.SetSide(true, _pinky); break;}
}
}

Refactoring if-else if - else

I have the following code example
if(object.Time > 0 && <= 499)
{
rate = .75m
}
else if(object.Time >= 500 && <= 999)
{
rate = .85m
}
else if(object.Time >= 1000)
{
rate = 1.00m
}
else
{
rate = 0m;
}
My question is what design pattern can I use to make this better?
Edit: Just to clarify a little better, the code you see here is something that currently exists within a Strategy Pattern Implementation. We have 3 types of calculations 2 of which has 3 different "rates" that could be used based off of the time you see below. I thought about creating a strategy implementation for each rate, but then I would be moving the logic for determining the strategy to use and make that a mess as well.
Thanks!
If you're really looking for a design pattern, I'd go for the Chain of Responsibility pattern.
Basically your "link" tries to handle the input. If it is unable to handle it, it's passed down the chain until an other link can handle it. You can also define an interface for easy mocking in your unit tests, if you have some.
So you have this abstract class that every link will inherit :
public abstract class Link
{
private Link nextLink;
public void SetSuccessor(Link next)
{
nextLink = next;
}
public virtual decimal Execute(int time)
{
if (nextLink != null)
{
return nextLink.Execute(time);
}
return 0;
}
}
And then you create each links with your rules :
public class FirstLink : Link
{
public override decimal Execute(int time)
{
if (time > 0 && time <= 499)
{
return .75m;
}
return base.Execute(time);
}
}
public class SecondLink : Link
{
public override decimal Execute(int time)
{
if (time > 500 && time <= 999)
{
return .85m;
}
return base.Execute(time);
}
}
public class ThirdLink : Link
{
public override decimal Execute(int time)
{
if (time >= 1000)
{
return 1.00m;
}
return base.Execute(time);
}
}
Finally, to use it, just set every successor and call it :
Link chain = new FirstLink();
Link secondLink = new SecondLink();
Link thirdLink = new ThirdLink();
chain.SetSuccessor(secondLink);
secondLink.SetSuccessor(thirdLink);
and all you have to do, is call the chain with one clean call:
var result = chain.Execute(object.Time);
There is a not so famous pattern called 'Rules Pattern'
The idea is that everything is extracted into an object and let it handle its own job. You will have each class for each rule that you defined which is your condition statement, e.g. (object.Time > 0 && <= 499)
public class RuleNumberOne : IRules
{
public decimal Execute(Oobject date)
{
if(date.Time > 0 && date.Something <= 499)
return .75m;
return 0;
}
}
public class RuleNumberTwo : IRules
{
public decimal Execute(Oobject date)
{
if(date.Time >= 500 && date.Something <= 999)
return .85m;
return 0;
}
}
public interface IRules
{
decimal Execute(Oobject date);
}
Therefore, on your class that used to look like this
if(object.Time > 0 && <= 499)
{
rate = .75m
}
else if(object.Time >= 500 && <= 999)
{
rate = .85m
}
else if(object.Time >= 1000)
{
rate = 1.00m
}
else
{
rate = 0m;
}
Will now be,
private List<IRules>_rules = new List<IRules>();
public SomeConstructor()
{
_rules.Add(new RuleNumberOne());
_rules.Add(new RuleNumberTwo());
}
public void DoSomething()
{
Oobject date = new Oobject();
foreach(var rule in this._rules)
{
Decimal rate = rule.Execute(date);
}
}
The idea here is that once you get nested if conditions, it would be harder to read the condition statements and its hard for the developer to make any changes. Thus, it separates the logic of each individual rule and its effect into its own class which follows the rule Single Responsibility Pattern.
Some considerations are
1.) Read only
2.) Explicit order
3.) Dependencies
4.) Priority
5.) Persistence
Again, consider using the Rules Pattern when you have a growing amount of conditional complexity and your application's requirements warrants it.
You can customize it if you want don't want it to return decimal or something but the idea is here.
You only need to check one endpoint of the range. The other one is implied by your actually being at that point in the code, since the earlier conditions were false.
if (obj.Time <= 0) {
rate = 0.00m;
}
// At this point, obj.Time already must be >= 0, because the test
// to see if it was <= 0 returned false.
else if (obj.Time < 500) {
rate = 0.75m;
}
// And at this point, obj.Time already must be >= 500.
else if (obj.Time < 1000) {
rate = 0.85m;
}
else {
rate = 1.00m;
}
It would be better to make the more common end of the scale the one you check first, for readability and performance reasons. But it'll work either way.
Using a map:
var map = new[]
{
new { Rule = (Func<Oobject, bool>) ( x => x.Time > 0 && x.Something <= 499 ),
Value = .75m },
new { Rule = (Func<Oobject, bool>) ( x => x.Time >= 500 && x.Something <= 999 ),
Value = .85m },
new { Rule = (Func<Oobject, bool>) ( x => true ),
Value = 0m }
};
var date = new Oobject { Time = 1, Something = 1 };
var rate = map.First(x => x.Rule(date) ).Value;
Assert.That( rate, Is.EqualTo(.75m));
I like the idea of #lll's Rules Pattern answer but it has a flaw.
Consider the following test (NUnit):
[Test]
public void TestRulesUsingList()
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = 0m;
foreach(var rule in rules)
rate = rule.Execute(date);
Assert.That( rate, Is.EqualTo(.75m));
}
The test fails. Although RuleNumberOne was called and returned a non-zero value, RuleNumberTwo was subsequently called and returned zero to overwrite the correct value.
In order to replicate the if..else..else logic, it need to be able to short circuit.
Here's a quick fix: change the interface's Execute method to return a bool to indicate whether to rule should fire and add a Value property to get the rule's decimal value. Also, add a defulat rule that alwasys evaluates true and returns zero. Then change the implementation (test) to get the value of the first rule to evaluate true:
[Test]
public void TestRulesUsingList2()
{
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo(),
new DefaultRule() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = rules.First(x => x.Execute(date)).Value;
Assert.That( rate, Is.EqualTo(.75m));
}
public class Oobject
{
public int Time { get; set; }
public int Something { get; set; }
}
public interface IRules
{
bool Execute(Oobject date);
decimal Value { get; }
}
public class RuleNumberOne : IRules
{
public bool Execute(Oobject date)
{
return date.Time > 0 && date.Something <= 499;
}
public decimal Value
{
get { return .75m; }
}
}
public class RuleNumberTwo : IRules
{
public bool Execute(Oobject date)
{
return date.Time >= 500 && date.Something <= 999;
}
public decimal Value
{
get { return .85m; }
}
}
public class DefaultRule : IRules
{
public bool Execute(Oobject date)
{
return true;
}
public decimal Value
{
get { return 0; }
}
}
You can go for a format and not a design-pattern in the if-else condition;
Generally, if you have lot of conditions I prefer if than lot of nested if-else's you can opt for something like this;
if(condition1){
return x; // or some operation
}
if(condition 2){
return y; // or some operation
}
return default; // if none of the case is satisfied.
I do not think this is a anti pattern Problem and for code metrics is also oki. The If is not nested and not very complex!.
But you might make better for example using Switch or you make own class which contains properties IsAgeBiggerThanMax() etc.
Switch update:
var range = (time - 1) / 499;
switch (range)
{
case 0: // 1..499
rate = 0.75;
break;
case 1: // 500.. 999
rate = 0.85;
break;
default:
rate = 0;
if (time == 1000)
{
rate = 1.0;
}
break;
}
Testing is a philosophy question we do not know what is this function and what is doing. maybe it can be tested 100% from outside!
I really like Leo Lorenzo Luis's Solution.
But instead of returning the Rate, I would let the Rule do something with it.
This will respect The S. from the S.O.L.I.D. Principles
and the Law Of Demeter.
Also, when a class "asks" for a value that is contained into another class, you can identify it as a smell called the data class. You should try to avoid this.
That being said: I would do two things to polish Leo Lorenzo's solution:
Call the right Rule without the for loop.
Executing the behavior requested inside it's associated Rule class.
In order to do this, we have to map the rule classes with their time range, so they can be accessed directly instead of having to iterate through a loop. You'll need to implement your own Map Object (or List Object, or Collection), overloading the [] operator and it's add function
so you can add your rules in your map like this for example:
ranges.Add(0,500).AddRule(rule1);
ranges.Add(500,1000).AddRule(rule2);
etc..
You can see above, there is an Object Range that can have an Object Rule associated to it. So you could eventually add more than one rule for the same Range.
Then, you call it like this:
ranges[Object.time].Execute(Object);
If you have a huge amount of "if" or if you want to put this information in a settings file then I would suggest you create a class to store this information.
Class
FromTime
ToTime
Value
values.Add(New Class(0, 499, .75));
values.Add(New Class(500, 999, .85));
values.Add(New Class(1000, 9999, 1));
Then you loop each items in the collection
if(object.Time >= curItem.FromTime && object.Time <= curItem.ToTime)
rate = curItem.Value;
You could always have nullable values or set -1 as infinite.
values.Add(New Class(-1, 0, 0));
values.Add(New Class(0, 499, .75));
values.Add(New Class(500, 999, .85));
values.Add(New Class(1000, -1, 1));
if((object.Time >= curItem.FromTime || curItem.FromTime == -1) && (object.Time <= curItem.ToTime || curItem.ToTime == -1))
rate = curItem.Value;
Just do one comparison in each if, and go top-to-bottom with the values:
if (Object.Time >= 1000)
rate = 1.0;
else
if (Object.Time >= 500)
rate = 0.85;
else
if (Object.Time > 0)
rate = 0.75;
else
rate = 0;

What is an effective way to validate a bunch of variables before moving on?

I've been reading about the ideal size of methods and the single responsibility principle then I go look at some of my code. I feel I can break up a lot (>90%) of my stuff to be small manageable methods but then I get to validating a data or a form. It always seems really large and bloated. I tend to validate my data with nested if statements and try to catch errors or issues at each level. But when I start to get 6, 8, 10+ levels of validation it is very cumbersome. But I'm not sure how to break it up to be more effective.
An example of something I think is cumbersome but not sure how to improve upon it is below.
Each of the levels has a unique action associated with it and only once all the conditions return true can the whole thing return true but this is tough to read, especially after coming back to the program after a month or so.
if (InitialUsageSettings.zeroed || sender.Equals(btnZero))
{
if (InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard))
{
if (InitialUsageSettings.ReferenceFilterRun || sender.Equals(btnReference) || sender.Equals(btnStandard))
{
if (InitialUsageSettings.PrecisionTestRun || sender.Equals(btnPrecision) || sender.Equals(btnReference) || sender.Equals(btnStandard))
{
if (txtOperatorID.Text.Length > 0 && cboProject.Text.Length > 0 && cboFilterType.Text.Length > 0 && cboInstType.Text.Length > 0)
{
if (txtFilterID.Text.Length > 0 && txtLot.Text.Length > 0)
{
return true;
}
else
{
if (txtFilterID.Text.Length == 0)
{
//E
}
if (txtLot.Text.Length == 0)
{
//D
}
}
}
else
{
if (txtOperatorID.Text.Length == 0)
{
//A
}
if (cboProject.Text.Length == 0)
{
//B
}
if (cboFilterType.Text.Length == 0)
{
//C
}
if (cboInstType.Text.Length == 0)
{
//D
}
//return false;
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: X");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: Y");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: Z");
}
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: A");
}
If your main purpose is to break the methods up into manageable chunks, you could encapsulate each if block in its own method. e.g.:
if (InitialUsageSettings.zeroed || sender.Equals(btnZero))
{
ValidateStandardFilter();
}
else
{
outputMessages.AppendLine("Please correct the folloring issues before taking a reading: A");
}
But it seems to me that this method has too many responsibilities: You're trying to make it validate and also output a message. Instead, the method should be solely responsible for validating.
public ValidationResult Validate(Sender sender)
{
if (!(InitialUsageSettings.zeroed || sender.Equals(btnZero)))
{
return ValidationResult.Error("A");
}
if (!(InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard)))
{
return ValidationResult.Error("Z");
}
// Etc...
if (txtOperatorID.Text.Length == 0)
{
errors.Add("A");
}
if (cboProject.Text.Length == 0)
{
errors.Add("B");
}
if (cboFilterType.Text.Length == 0)
{
errors.Add("C");
}
if (cboInstType.Text.Length == 0)
{
errors.Add("D");
}
if(errors.Count > 0)
{
return ValidationResult.Errors(errors);
}
if (txtFilterID.Text.Length == 0)
{
errors.Add("E");
}
if (txtLot.Text.Length == 0)
{
errors.Add("D");
}
return errors.Count > 0
? ValidationResult.Errors(errors)
: ValidationResult.Success();
}
And then the calling code can worry about the output:
var result = Validate(sender);
if (result.IsError)
{
outputMessages.AppendLine("Please correct...: " + result.Issue);
}
To get an idea of what the ValidationResult class might look like, see my answer here.
Update
The code above could be further refactored to reduce repetition even more:
public ValidationResult Validate(Sender sender)
{
if (!(InitialUsageSettings.zeroed || sender.Equals(btnZero)))
{
return ValidationResult.Error("A");
}
if (!(InitialUsageSettings.StandardFilterRun || sender.Equals(btnStandard)))
{
return ValidationResult.Error("Z");
}
// Etc...
var firstErrorBatch = GetEmptyStringErrors(
new[]{
new InputCheckPair(txtOperatorID, "A"),
new InputCheckPair(cboProject, "B"),
new InputCheckPair(cboFilterType, "C"),
new InputCheckPair(cboInstType, "D"),
})
.ToList();
if(firstErrorBatch.Count > 0)
{
return ValidationResult.Errors(firstErrorBatch);
}
var secondErrorBatch = GetEmptyStringErrors(
new[]{
new InputCheckPair(txtFilterID, "E"),
new InputCheckPair(txtLot, "D"),
})
.ToList();
return secondErrorBatch.Count > 0
? ValidationResult.Errors(secondErrorBatch)
: ValidationResult.Success();
}
private class InputCheckPair
{
public InputCheckPair(TextBox input, string errorIfEmpty)
{
Input = input;
ErrorIfEmpty = errorIfEmpty;
}
public TextBox Input {get; private set;}
public string ErrorIfEmpty{get; private set;}
}
public IEnumerable<string> GetEmptyStringErrors(IEnumerable<InputCheckPair> pairs)
{
return from p in pairs where p.Input.Text.Length == 0 select p.ErrorIfEmpty;
}
Something akin to
if(errorCondition1)
errors.add(message1);
if(errorCondition2)
errors.add(message2);
return errors.Count == 0;
So each condition is not nested
You can invert your if statements and use Guard Clauses instead. See this example.
Reverse the flow. Instead of
If(cond) {
if(someothercond) {
//great sucess!
return true;
} else {
// handle
return false;
}
} else {
// handle
return false;
}
do:
if(!cond1) {
// handle
return false;
}
if(!someothercond) {
// handle
return false;
}
// great sucess!
return true;
One way is to have a validation method that is called prior to executing your other code.
For example:
private String ValidateThis() {
StringBuilder result = new StringBuilder();
if (!cond1) {
result.AppendLine("error on cond1");
}
if (!cond2) {
result.AppendLine("error on cond2");
}
return result.ToString();
}
public void ButtonClick(object sender) {
String isValid = ValidateThis();
if (!String.IsNullOrEmpty(isValid)) {
// set your error message
outputMessages.AppendLine(isValid);
return;
}
// ... perform your other operations.
}
I would try to have each validation defined as a predicate, something like this...
delegate bool Validator(object sender, out string message);
Then you could string as many of those together as you need.
There are a number of ways to tackle this. You really want to limit the amount of repeated code, such as the code that adds an output message, which is nearly identical in four or more places.
If you think of these nested if…else blocks as a sequence, where as soon as one fails you take action and stop further processing, you can create a list and leverage LINQ's FirstOrDefault functionality to process the list of conditions sequentially until one fails, or you get null if they all pass.
Creating an object to encapsulate the conditions will help consolidate and reduce duplication.
Here is an example:
public class Validator
{
public Validator(string code, bool settingsCheck, Button button, object sender)
{
Code = code;
IsValid = sender != null && button != null && sender.Equals(button);
}
public bool IsValid { get; private set; }
public string Code { get; private set; }
}
Now, your method looks more like this:
var validationChecks = new List<Validator>
{
new Validator("A", InitialUsageSettings.zeroed, btnZero, sender),
new Validator("Z", InitialUsageSettings.StandardFilterRun, btnStandard, sender),
new Validator("Y", InitialUsageSettings.ReferenceFilterRun, btnReference, sender),
new Validator("X", InitialUsageSettings.PrecisionTestRun, btnPrecision, sender)
}
var failure = validationChecks.FirstOrDefault(check => !check.IsValid);
if (failure != null)
{
outputMessages.AppendLineFormat(
"Please correct the following issues before taking a reading: {0}", failure.Code);
return;
}
else
{
// further checks; I'm not sure what you're doing there with A-E
}

Categories