How to add to a chain of methods by checking if statements - c#

I don't know the right terminology for this but i have a simple C# code snippet which tweens some objects like this:
camera.gameObject.transform.DOMove(target,3.0f)
.SetEase(Ease.InOutQuad)
.OnComplete(animation.FadeIn);
But what i need to do is add another method to this chain based on a certain condition like this:
camera.gameObject.transform.DOMove(target,3.0f)
.SetEase(Ease.InOutQuad)
//the general idea
if(visible == true){
.OnStart(animation.FadeOut);
}
.OnComplete(animation.FadeIn);
Obviously this is a syntax error, but i do not know the correct way to handle something like this for the syntax.
How should i approach it?

You would need to place the entire chunk in your if-else statement, you cannot break it down:
if(visible == true){
camera.gameObject.transform.DOMove(target,3.0f)
.SetEase(Ease.InOutQuad) .OnStart(animation.FadeOut).OnComplete(animation.FadeIn);
}
else {
camera.gameObject.transform.DOMove(target,3.0f)
.SetEase(Ease.InOutQuad).OnComplete(animation.FadeIn);
}
Alertnatively:
var intermediateObject = camera.gameObject.transform.DOMove(target,3.0f)
.SetEase(Ease.InOutQuad);
if (visible) {
intermediateObject.OnStart(animation.FadeOut).OnComplete(animation.FadeIn);;
}
else {
intermediateObject.OnComplete(animation.FadeIn);;
}
The var keyword means that you do not need to worry about the type of the object yourself, but then again, its usage does hinder readability (in my opinion).

If you want to keep everything in one chain you can try using If extension:
internal static T If<T> (this T source, bool isTrue, Action<T> thenAction) {
if (isTrue) {
thenAction(source);
}
return source;
}
This extension will work if OnStart returns same camera object. Otherwise, If extension should be changed.
Then your code would look like this:
camera.gameObject.transform.DOMove(target,3.0f).
SetEase(Ease.InOutQuad)
If(visible == true, value => value.OnStart(animation.FadeOut)).
OnComplete(animation.FadeIn)
If OnStart actually returns different object:
internal static T If<T> (this T source, bool isTrue, Func<T, T> thenFunction) =>
isTrue ? thenFunction(source) : source;

Related

Use custom attribute to skip body method

I have the following function:
public void Test(string testString)
{
//Do Stuff
}
At some points in my code, I have to repeatedly check if the parameter is empty string/null/whitespace to skip the body method. The usual ways I've done this till now, are the following:
public void Test(string testString)
{
if(!string.IsNullOrWhiteSpace(testString))
{
//Do Stuff only if string has text in it.
}
}
Or
public void Test(string testString)
{
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
Is there a way to create a custom attribute that checks if the parameter of the function is empty etc, to skip the method? I've had some experiece (basic stuff), with custom attributes, but I can't figure out a way to make the attribute skip the method body.
The ideal end product of the implementation would be the following:
[SkipIfEmptyParameter]
public void Test(string testString)
{
//Do Stuff only if string has text in it.
}
Of course, any suggestion is welcome that helps minimize the recurring code if the attribute implementation is not possible.
Edit: Example of the problem I want to solve.
I have the following methods. I get from Microsoft Test Manager, some parameters that our test scenario are expecting (what the values should be). There is a SharedStep implementation that asserts the user's info:
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's name at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserSurname(string surname)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's surname at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserAge(string age)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's age at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserHeight(string height)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's height at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
The "Do Stuff" contain Selenium implementation that handle WebElements and might be time consuming, so if we don't want to validate that specific value, we just skip the whole method.
Now, when creating the scenarios over to Microsoft Test Manager, the shared steps allows the tester to decide what elements of the page will be validated. If some of the parameters are empty, then the code just skips the blocks and goes to w/e validation the user wants (still, the implementation is for every info the user has, but we just assign value to each parameter we want to test, and every parameter that does not have a value, just gets it's method body skipped).
The problem is, if I want to change the condition of skipping the method, I will have to go to each method and manually change the IF statement. Hence why I though it might be a good idea to have an attribute for every method that validates information.
P.S. I'm talking about hundreds of methods that have the IF implementation at the start.
The only way that I know that this can be done using attributes is aspect oriented programming using a product like post sharp and method interception. Alternatively if the methods are defined in an interface this can also be done by using RealProxy but seems more than a little overkill.
The way you are doing it is actually pretty good. But as Evk pointed out in the comments: You should extract the "skip checking" into a separate method, especially if the check is always the same and needs to be changed globally. Using an attribute would solve the problem, but is a little complicated to use.
Instead, take a look at the code below. Looks pretty clear, doesn't it? Don't use too many comments (and don't copy-paste them into every method, that is of no use). This way, you have the same benefits as if you would use a custom attribute but without the ugliness of using reflection.
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
if (ShouldSkipValidation(name)) return;
// code here...
}
private void VerifyUserSurname(string surname)
{
if (ShouldSkipValidation(surname)) return;
// code here...
}
private void VerifyUserAge(string age)
{
if (ShouldSkipValidation(age)) return;
// code here...
}
private void VerifyUserHeight(string height)
{
if (ShouldSkipValidation(height)) return;
// code here...
}
// The MTM scenario does not want to validate values that satisfy the check below
private bool ShouldSkipValidation(string value)
{
return string.IsNullOrWhiteSpace(value) || value == "<>";
}
I don't think attributes make it possible to achieve what you are trying to achieve.
But you can use a custom method invoker instead:
static void Main(string[] args)
{
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), null);
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "");
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "abc");
// RESULT:
// Trying to invoke action...
// Trying to invoke action...
// Trying to invoke action...
// I have been invoked!
}
static void InvokeIfNotNullOrWhitespace(Action<string> action, string inputString)
{
Console.WriteLine("Trying to invoke action...");
if(!string.IsNullOrWhiteSpace(inputString))
action.DynamicInvoke(inputString);
}
static void TestMethod(string input)
{
Console.WriteLine("I have been invoked!");
}
The reason why I think attributes won't work is because they can't control what is going on inside the method. Instead, "other external things" can look at those attributes and decide what to do.
To achieve what you are trying to achieve, an "external thing" would need to look at the attribute and decide if it is executed or not. This would be equivalent to what I wrote: an external invoker that unifies the "check string validity" procedure.
Here are my 4 cents on this,
Calling an attribute involves reflection, already a bad idea as
you need to find out if the attribute is set;
You're avoiding a "1 liner" in your code that actually is quite
easy to type;
Use method overloading;
You can use Aspect oriented programming that will basically inject the below samples in your code at compile time. You can control the way this works with annotations and would not have a negative effect on the generated runtime.
Here are some variations:
//1
if(string.IsNullOrEmpty(testString))
return;
//2
if(string.IsNullOrEmpty(testString) ||string.IsNullOrWhiteSpace(testString) )
return;
When going for 3 just make sure you do not mix returning null, or boolean true/false based on the "missing" text. Only you know how your code should flow.
Perhaps you are looking for method overloading
you can do that by creating 2 methods with the same name in the same class.
You can call the empty MyMethod() from the MyMethod(with string) so you do not duplicate the logic.
return string.IsNullOrEmpty(testString)?MyMethod():MyMethod(testString);

Is it possible to break out of a loop or continue to the next iteration from an external method?

I have a validation method which I call in a loop.
I want to call "continue" if the validation fails.
Is there a way to call "continue" from the validation method ?
I just don't want to call "continue" in so many places in the loop...
No, flow control statements only affect the blocks within which they are defined. The only built-in way to alter control flow from further up the stack like that is an exception, which is definitely the wrong mechanism for what you are doing.
If you are bothered by all the continues, I suggest you consider moving towards a more declarative way of thinking. Define the body of your validation loop like so:
bool IsValid(Foo foo) {
if (Condition1(foo)) {
return false;
}
if (Condition2(foo)) {
return false;
}
// ... and so on
}
and then validate like this:
if (!foos.All(IsValid)) {
// One of your foos is invalid
}
the LINQ extension methods All and Any will break execution as soon as they can, meaning that All will stop when it finds the first one that doesn't satisfy the condition and Any will stop when it finds the first one that does.
You have a lot of continues in your cycle and it becomes bothering. You cannot continue from the external method, as it is out of scope. There are several solutions actually though:
You can return a boolean value from your validation methods and then use it as such:
if (!IsValid()) {
continue;
}
It is not helpful though, because you will still have continues.
You can put your validations at the start of the cycle and you can use a flag to determine whether the iteration should step out, initialized by false:
while (myCondition) {
stepOut = false;
//validation region, you set stepOut to false if a validation fails
if (!stepOut) {
//operations
}
}
You can wrap all the validation call into a method, let's call it myValidation and then:
while (myCondition) {
if (myValidation()) {
//operations
}
}
or
while (myCondition) {
if (!IsValid()) {
//continue
}
}
You can throw an Exception, but DON'T do that.
Just return false in your validation method wherever it should return, then check if the validation method returns false, break out of loop in caller function.
Why Not ?
Golden Rule in Programming : "There is always a way".
C++ lets you inline Assembly Language syntax. Similar to it, C# supports it too. Let me consider your example.
void method1(){
foreach(var x in y)
{
Validate(x);
...
//Your other logic
...
EndOfLoop:
;
}
}
..
..
void Validate(T x)
{
#if IL
br EndOfLoop
#endif
}
//End Of Code
This will "jump" to the "EndOfLoop" Label from anywhere within your Code. This could be a bad practice depending on your code though..

Run event once during Update() XNA / C#

this is the best way I can think of doing this. Could you give me so hints as to whether this is the correct way or if there is a more efficient way of doing it.
My situation is:
Each time the frame is Update()'ed (Like in XNA) I want to check if something has happened.. Like if the timer for that screen has been running for over 2000 milliseconds. But I only want it to fire once, not every time the frame is updated. This would cause a problem:
if(totalMilliseconds > 2000)
{
this.Fader.FadeIn();
}
So I came up with this method that I have implemented in the GameScreen class that looks like this:
public bool RunOnce(string Alias, bool IsTrue)
{
if (!this.Bools.ContainsKey(Alias))
this.Bools.Add(Alias, false);
if (IsTrue && !this.Bools[Alias])
{
this.Bools[Alias] = true;
return true;
}
else
return false;
}
This basically checks if the passed if statement boolean is true, if it is then it fires once and not again unless the Bool["Alias"] is set back to false. I use it like this:
if(this.RunOnce("fadeInStarted", totalMilliseconds > 2000))
{
this.Fader.FadeIn();
}
This will then only run one time and I think is quite easily readable code-wise.
The reason I have posted this is for two reasons.. Firstly because I wanted to show how I have overcome the problem as it may be of some help to others who had the same problem.. And secondly to see if I have missed an obvious way of doing this without creating a manual method for it, or if it could be done more efficiently.
Your method is interesting, I don't see a problem with it, you've essentially created a new programming construct.
I haven't encountered this situation a lot so what I have done in this situation is always start with the untidy approach:
bool _hasFadedIn = false;
.
if(totalMilliseconds > 2000 && !_hasFadedIn)
{
this.Fader.FadeIn();
_hasFadedIn = true;
}
And 90% of the time I leave it like that. I only change things if the class starts growing too big. What I would do then is this:
_faderControl.Update(totalMilliseconds);
Put the logic for fader control into a separate class, so:
class FaderControl
{
bool _hasFadedIn=false;
public void Update(int totalMilliseconds)
{
if (_hasFadedIn)
return;
if (totalMilliseconds <= 2000)
return;
this.Fader.FadeIn();
_hasFadedIn=true;
}
}
It can be modified to make it configurable, like reseting, setting "start", "end", fadein time, or also controlling fadeout too.
Here's how I would approach this problem.
These are your requirements:
You have arbitrary pieces of logic which you want to execute inside of your Update().
The logic in question has a predicate associated with it which determines whether the action is ready to execute.
The action should execute at most once.
The core concept here is "action with an associated predicate," so create a data structure which represents that concept:
public class ConditionalAction
{
public ConditionalAction(Action action, Func<Boolean> predicate)
{
this.Action = action;
this.Predicate = predicate;
}
public Action Action { get; private set; }
public Func<Boolean> Predicate { get; private set; }
}
So now, your example becomes
var action = new ConditionalAction(
() => this.Fader.FadeIn(),
() => totalMilliseconds > 2000);
In your Update() you need something that can execute these conditional actions:
public void Update(GameTime time)
{
// for each conditional action that hasn't run yet:
// check the action's predicate
// if true:
// execute action
// remove action from list of pending actions
}
Because their predicates are probably unrelated, actions don't necessarily run in order. So this isn't a simple queue of actions. It's a list of actions from which actions can be removed in arbitrary order.
I'm going to implement this as a linked list in order to demonstrate the concept, but that's probably not the best way to implement this in production code. Linked lists allocate memory on the managed heap, which is generally something to be avoided in XNA. However, coming up with a better data structure for this purpose is an exercise best left for another day.
private readonly LinkedList<ConditionalAction> pendingConditionalActions =
new LinkedList<ConditionalAction>();
public void Update(GameTime time)
{
for (var current = pendingConditionalActions.First; current != null; current = current.Next)
{
if (current.Value.Predicate())
{
current.Value.Action();
pendingConditionalActions.Remove(current);
}
}
}
public void RegisterConditionalAction(ConditionalAction action)
{
pendingConditionalActions.AddLast(action);
}
Registered actions will wait until their predicates become true, at which point they will be executed and removed from the list of pending actions, ensuring that they only run once.

Cleaner code: Re-factor multiple nested if statements

I have code that looks something like this:
if(condition1)
{
//do some stuff
if(condition2)
{
//do some other stuff
if(condition3)
{
//do some more stuff
if(condition4)
{
//you probably got the point by now...
}
}
}
And I would like to re-factor it to code that looks better and is easier to follow.
So far the best I got Is:
do{
if(!condition1){break;}
//do some stuff
if(!condition2){break;}
//do some other stuff
if(!condition3){break;}
//do some more stuff
if(!condition4){break;}
//you probably got the point by now...
}while(false);
My question is:
Is there another better way I am missing?
I don't think it is relevant, but I am using C#...
Possibly encapsulate the functionality you need for each boolean condition into a method and use the method instead of specifying condition1, condition2, condition3 etc.
private boolean isRed() {
//do some stuff
}
private boolean isBlue() {
//do some other stuff
}
private boolean isGreen() {
//do some more stuff
}
...
if(isRed() && isBlue() && isGreen()) {
//do some more stuff
}
Since you are using C#, the idea of #dseibert could be extended a little bit more and made flexible using delegates, in this case Func.
You could create a List that holds Func's and add as many functions with the signature bool function(void) as you want and then evaluate the result of all of them using LINQ.
Three example functions to play with:
private bool isRed()
{
System.Console.WriteLine("red");
return true;
}
private bool isBlue()
{
System.Console.WriteLine("blue");
return false;
}
private bool isGreen()
{
System.Console.WriteLine("green");
return true;
}
List holding Funcs, that is filled with the test functions and initialized result:
var actions = new List<Func<bool>>();
actions.Add(() => isRed());
actions.Add(() => isGreen());
actions.Add(() => isBlue());
var result = true; // initial value
Evaluate all functions at once:
actions.ForEach(a => result &= a());
System.Console.WriteLine(result);
Now the only thing that you need to do is create a new method and add it to the list.
The downside of this solutions is that every method is always called even if the result is already false, but the code within the ForEach extension method could be optimized.

Passing statement lambda as parameter

After following this question on updating a GUI from another thread I wanted to extend the code slightly so that it worked for something other than property assignment. Specifically I was trying to find a way to assign some functionality directly to a lambda so that I can define the behavior as needed (I modified the original slightly for WPF):
private delegate void UpdateControlThreadSafeDelegate(Control control, System.Linq.Expressions.Expression<Action> property);
public void UpdateControl(Control control, System.Linq.Expressions.Expression<Action> property)
{
// If calling thread is not associated with control dispatcher, call our thread safe property update delegate
if (!control.Dispatcher.CheckAccess())
{
control.Dispatcher.Invoke(new UpdateControlThreadSafeDelegate(UpdateControl), new object[] { control, property });
}
else
{
Action call = property.Compile();
call();
}
}
With usage:
UpdateControl(lbFoo, () => lbFoo.Items.Clear()); // where lbFoo is a ListBox control
This works fine. But I'd rather allow do something like:
UpdateControl(lbFoo, () => { lbFoo.Items.Clear(); lbFoo.Items.Add("Bar");});
This does not work, returning error CS0834: A lambda expression with a statement body cannot be converted to an expression tree. The error is clear, I'm just not certain on how best to proceed. I could follow my original usage and do what I need in several lines, it's just not as tidy.
I'm guessing there is a better/easier way to do what I want.
If you don't use expressions, and just pass the action, like so:
public void UpdateControl(Control control, Action actionToExecute)
Then you can use this as written. The only other change will be your else statement, where you would just call this directly:
else
{
actionToExecute();
}

Categories