tags:

views:

180

answers:

4

Hey everyone,

Using C#, I need to do some extra work if function A() was called right before function C(). If any other function was called in between A() and C() then I don't want to do that extra work. Any ideas that would require the least amount of code duplication?

I'm trying to avoid adding lines like flag = false; into every function B1..BN.

Here is a very basic example:

bool flag = false;

void A()
{
    flag = true;
}

void B1()
{
    ...
}

void B2()
{
    ...
}

void C()
{
    if (flag) 
    {
        //do something
    }
}

The above example was just using a simple case but I'm open to using something other than booleans. The important thing is that I want to be able to set and reset a flag of sorts so that C() knows how to behave accordingly.

Thank you for your help. If you require clarification I will edit my post.

+7  A: 

Why not just factor your "Extra work" into a memoised function (i.e. one that caches its results)? Whenever you need that work you just call this function, which will short circuit if the cache is fresh. Whenever that work becomes stale, invalidate the cache. In your rather odd examples above, I presume you'll need a function call in each of the Bs, and one in C. Calls to A will invalidate the cache.

If you're looking for away around that (i.e. some clever way to catch all function calls and insert this call), I really wouldn't bother. I can conceive of some insane runtime reflection proxy class generation, but you should make your code flow clear and obvious; if each function depends on the work being already done, just call "doWork" in each one.

Adam Wright
yeah i figured there's no easy way to do this. the functions can be called in any order. it's only that particular order of A(),C() that requires the extra work, but if I set a flag in A() and don't reset it when B1() or B2() is called then in C() I get the incorrect behavior.
gtaborga
+1 for the reference to reflection; and for the "insane" labeling, extremely accurate in this case ;)
herenvardo
+3  A: 

Sounds like your design is way too tightly coupled if calling one method changes the behavior of another such that you have to make sure to call them in the right order. That's a major red flag.

Sounds like some refactoring is in order. It's a little tricky to give advice without seeing more of the real code, but here is a point in the right direction.

Consider adding a parameter to C like so:

void C(bool DoExtraWork) {
  if (DoExtraWork)...
}

Of course "DoExtraWork" should be named something meaningful in the context of the caller.

JohnFx
I have seen similar coding patterns and, *on some cases*, they are justified. After all, having a method's behavior depend on the state of its class *is* reasonable :P
herenvardo
+1  A: 

I solved a problem with a similar situation (i.e., the need to know whether A was called directly before C) by having a simply state machine in place. Essentially, I built a state object using an enum and a property to manage/query the state.

When my equivalent of A() was called, it would have the business logic piece store off the state indicating that A was called. If other methods (your B's ) were called, it would toggle the state to one of a few other states (my situation was a bit more complicated) and then when C() was called, the business logic piece was queried to determine if we were going to call some method D() that held the "only if A was just called" functionality.

I suspect there are multiple ways to solve this problem, but I liked the state machine approach I took because it allowed me to expand what was initially a binary situation to handle a more complicated multi-state situation.

I was fortunate that multi-threading was not an issue in my case because that tends to make things more entertaining, but the state machine would likely work in that scenario as well.

Just my two cents.

itsmatt
It turns out I was able to solve it using something similar to that. I used an enumeration and found a cleaner solution which didn't require coupling function A() and C().
gtaborga
A: 

I don't recommend this, but what the hell: If you're willing to replace all your simple method calls:

A();

... with syntax like this:

// _lastAction is a class-level Action member
(_lastAction = new Action(A)).Invoke();

... then inside of C() you can just do a check like this:

void C()
{
    if (_lastAction.Method.Name == "A")
    {

    }
}

This probably isn't thread-safe (and it wouldn't work in code run through an obfuscator without a bit of tinkering), so I wouldn't use something like this without heavy testing. I also wouldn't use something like this period.

Note: my ancient version of C# only has Action<T> (and not Action or Action<T, T> etc.), so if you're stuck there, too, you'd have to add a dummy parameter to each method to use this approach.

MusiGenesis
I agree this kind of stuff is messy as hell. I just didn't think of a good solution at the time, but I found one that worked without the mess. Thank you for your efforts.
gtaborga