Most efficient way of evaluating independent variable for a similar outcome - c#

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;}
}
}

Related

C# repeating Enum elements

thanks in advance. I'm a Unity developer.
So I have my AI states in enum converted to a list.
public enum IdleState
{
BasicIdle,
PlayingWithKids,
Playfull,
Curious,
Bored,
MoveToCamera,
Waiting,
PlantMode,
Shy,
Crying
}
public List<IdleState> availableIdleStates = new List<IdleState>()
{
IdleState.BasicIdle,
IdleState.PlayingWithKids,
IdleState.Playfull,
IdleState.Curious,
IdleState.Bored,
IdleState.Waiting,
IdleState.PlantMode,
IdleState.Shy,
IdleState.Crying
};
I'm controlling the order of execution through my public list in my inspector witch works fine, however I would like to have basic idle (enum int = 0) execute multiple times in my inspector order of execution. Although when the list gets to my second basic idle it restarts and gets stuck between the two basic idles I assume its because its value in enum is 0, but i really don't know whats causing this, any help would be a blessing. thanks guys!
private void FixedUpdate()
{
if (Time.timeSinceLevelLoad > prevIdleStateChangeTime + currentStateDuration)
{
int i = availableIdleStates.FindIndex(x => x.Equals(currentIdleState))+1;
if (i >= availableIdleStates.Count)
{
i = 0;
}
changeState(availableIdleStates[i]);
}
switch (currentIdleState)
{
case IdleState.BasicIdle:
if (Time.timeSinceLevelLoad > subStateChangeTime + subStateDuration)
{
subStateChangeTime = Time.timeSinceLevelLoad;
switch (randInt)
{
//something
}
}
break;
case IdleState.PlayingWithKids:
if (Time.timeSinceLevelLoad > subStateChangeTime + subStateDuration)
{
int randInt = Random.Range(0, 3);
subStateChangeTime = Time.timeSinceLevelLoad;
switch (randInt)
{
//something
}
}
break;
etc..
every state change this method is being called:
private void changeState(IdleState NewState)
{
currentIdleState = NewState;
prevIdleStateChangeTime = Time.timeSinceLevelLoad;
mover.resetParameters();
subStateChangeTime = Time.timeSinceLevelLoad;
subStateDuration = -1;
}
availableIdleStates.FindIndex(x => x.Equals(currentIdleState))
Here. If first and second object is the same this will always find first occurence of your duplicated state (id = 0), your script changes it to id = 1 but in next update again first element is found and your id is back to 0. You should have field for that int value instead of finding index on list if you want to have duplicate elements.

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
}
}
}

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;

Creating,using and comparing elements within a button collection

I'm making a Tic-tac-toe project, and I'm having some difficulties. I've only gotten a loose grip about collections, so you can see the problem.
Thing is, I created 9 buttons which change their Background image when clicked, and disable themselves. I've managed to make it run for 2 players, but my wish is to create some sort of an AI.
I need a button collection so I can compare their properties, and avoid the usual one-by-one comparison and massive and numerous If statements.
What I actually want is to be able to test whether buttons in the same row or column have the same values (background images). What I've used so far is an array of strings that describes the sign value, but it's entirely detached from the buttons, and it would take a lot of time to type out all that code.
If it cannot be done the way I imagined it, please do tell. I am open to suggestions, and would be most grateful.
Oh, and if you need any code, or further detail, let me know.
You need to separate data (array) and presentation (buttons).
Update
I published a sample console project that compiles and runs.
Its model is separate from presentation so you can take TicTacToe.cs and write a GUI for it.
You don't need strings; booleans are fine for two states.
In fact, there is a third state, which is empty, so you can use a nullable boolean.
So X would correspond to true, O to false, and empty space to null.
I'd create a class that encapsulates a nullable boolean square array:
class TicTacToe {
const int Length = 3;
private bool? [][] _data;
private bool? _winner;
public TicTacToe ()
{
_data = Enumerable
.Range (0, Length)
.Select (_ => new bool? [Length])
.ToArray ();
}
}
Then I'd represent rows, columns and diagonals as vectors:
public bool? GetCell (int row, int column)
{
return _data [row][column];
}
public IEnumerable<bool?> GetRow (int index)
{
return _data [index];
}
IEnumerable<int> GetIndices ()
{
return Enumerable.Range (0, Length);
}
public IEnumerable<bool?> GetColumn (int index)
{
return GetIndices ()
.Select (GetRow)
.Select (row => row.ElementAt (index));
}
public IEnumerable<bool?> GetDiagonal (bool ltr)
{
return GetIndices ()
.Select (i => Tuple.Create (i, ltr ? i : Length - 1 - i))
.Select (pos => GetCell (pos.Item1, pos.Item2));
}
public IEnumerable<IEnumerable<bool?>> GetRows ()
{
return GetIndices ()
.Select (GetRow);
}
public IEnumerable<IEnumerable<bool?>> GetColumns ()
{
return GetIndices ()
.Select (GetColumn);
}
public IEnumerable<IEnumerable<bool?>> GetDiagonals ()
{
return new [] { true, false }
.Select (GetDiagonal);
}
public IEnumerable<IEnumerable<bool?>> GetVectors ()
{
return GetDiagonals ()
.Concat (GetRows ())
.Concat (GetColumns ());
}
Then I'd write a function that takes a vector and says if it's a winning one:
static bool? FindWinner (IEnumerable<bool?> vector)
{
try {
return vector
.Distinct ()
.Single ();
} catch (InvalidOperationException) {
return null;
}
}
static bool? FindWinner (IEnumerable<IEnumerable<bool?>> vectors)
{
return vectors
.Select (FindWinner)
.FirstOrDefault (winner => winner.HasValue);
}
public bool? FindWinner ()
{
return FindWinner (GetVectors ());
}
Now we can call GetWinner to find out if somebody already won.
Then I'd write a method to make a move:
public bool MakeMove (int row, int column, bool move)
{
if (_winner.HasValue)
throw new InvalidOperationException ("The game is already won.");
if (_data [row][column].HasValue)
throw new InvalidOperationException ("This cell is already taken.");
_data [row][column] = move;
_winner = FindWinner ();
return move == _winner;
}
public bool? Winner {
get { return _winner; }
}
This was all inside TicTacToe class.
Your GUI should create it and call its methods.
When a button gets clicked, this is what you may do:
private TicTacToe _game = new TicTacToe ();
private Button [][] _buttons = new Button [][3];
const bool HumanPlayer = true;
const bool AIPlayer = false;
public void HandleButtonClick (object sender, EventArgs e)
{
// Assuming you put a Tuple with row and column in button's Tag property
var position = (Tuple<int, int>) ((Button) sender).Tag;
var row = position.Item1;
var column = position.Item2;
// Sanity check
Debug.Asset (sender == _buttons [row][column]);
bool won = _game.MakeMove (row, column, HumanPlayer);
if (won) {
MessageBox.Show ("You won.");
}
RefreshButtons ();
}
void RefreshButtons ()
{
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var btn = _buttons [i][j];
var cell = _game.GetCell (i, j);
btn.Enabled = !cell.HasValue;
btn.Text = cell.HasValue
? (cell.Value ? "X" : "O")
: string.Empty;
}
}
}
Your AI should also call MakeMove and do its calculations based on information from calling GetRow, GetColumn and GetDiagonal.
I didn't check the code, it's only a sketch. (But the console project should run just fine.)
What I would use is a game state class that contains the current state of the game. For example:
public class Game
{
// These will have null for unselected, true for circle, false for cross, or something like that
public bool?[][] SquareStates = new bool?[3][3];
// Maybe a property to show a game is in progress
public bool GameInProgress = false;
// Maybe a function to restart game
public void Restart() { ... }
// And maybe a function to check for a winner
public string CheckWinner() { ... }
// Maybe another function to make AI make its next move
// and updates SquareStates.
public void AINextMove(out int row, out int column) { ... }
}
Once you have a class like that, your form would simply contain an intance of Game and then update the array of SquareStates as buttons are pressed and then checks for winner, calls AINextMove, checks for winner again, then updates its own button states with the new SquareStates.

Optimizing "this" type of loop

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 ;
}
}

Categories