Women Viagra

4Sep/084

Buy Viagra Pills

Buy viagra pills I find myself sometimes wishing I had a better switch/case construct in C#.

Buy viagra pills My requirements of "better" are:

  • Case statements are automatically scoped
  • I can switch on more than simple types
  • I can have custom logic for my matching criteria

But why not just use if/else if/else...?

Buy viagra pills Good question, buy viagra pills I'm glad you asked! However, buy viagra pills I don't have an excellent answer other than personal preference. Buy viagra pills if/else if/else is okay sometimes, buy viagra pills but other times I have a deterministic set of conditions, buy viagra pills and a switch type construct feels more symmetrical to me. Buy viagra pills I loves me some symmetric feeling code, buy viagra pills it just feels cleaner somehow.

Buy viagra pills So I'll present a somewhat contrived example just so you can see what the usage looks like, buy viagra pills then we'll see the code.

Usage


public void DoSomething()
{
	object foo = new object();
	object bar = new object();
	object baz = new object();

	Switch<object>.On(baz)
		.Case(x => x.Equals(foo), buy viagra pills () =>
		{
			Console.WriteLine("came into foo case");
		})
		.Case(x => x.Equals(bar), buy viagra pills () =>
		{
			Console.WriteLine("came into bar case");
		})
		.Default( () =>
		{
			Console.WriteLine("came into default case");
		})
		.Go();
}

Buy viagra pills The output from the above, buy viagra pills is as you'd expect, buy viagra pills the default case, buy viagra pills since baz wasn't equal to foo or bar.

Implementation


public class Switch<T>
{
	private T _target;
	private List<KeyValuePair<Predicate<T>, buy viagra pills Action>> _cases;
	private Action _default;

	public static Switch<T> On(T target)
	{
		return new Switch<T>(target);
	}

	public Switch(T target)
	{
		_target = target;
		_cases = new List<KeyValuePair<Predicate<T>, buy viagra pills Action>>();
	}

	public Switch<T> Case(Predicate<T> @case, buy viagra pills Action action)
	{
		_cases.Add(new KeyValuePair<Predicate<T>, buy viagra pills Action>(@case, buy viagra pills action));
		return this;
	}

	public Switch<T> Default(Action action)
	{
		_default = action;
		return this;
	}

	public void Go()
	{
		foreach(var @case in _cases)
			if (@case.Key(_target))
			{
				@case.Value();
				return;
			}
		if (_default != null)
			_default();
	}
}

Buy viagra pills The only part I don't really like is having to kick it off with the Go() at the end. Buy viagra pills Any ideas for a better way to kick it off, buy viagra pills or at least a better name for it (instead of Go).

Buy viagra pills Feedback? Ideas?

Update

Buy viagra pills Paul had a great idea a couple great ideas (see comments) on how to get rid of the Go() at the end, buy viagra pills and to force Default to only appear at the end. Buy viagra pills Here is the new implementation. Buy viagra pills Usage is the same, buy viagra pills just remove the Go().


public class Switch<T>
{
	private T _target;
	private bool _alreadyMatched;

	public static Switch<T> On(T target)
	{
		return new Switch<T>(target);
	}

	public Switch(T target)
	{
		_target = target;
		_alreadyMatched = false;
	}

	public Switch<T> Case(Predicate<T> @case, buy viagra pills Action action)
	{
		if (!_alreadyMatched && @case(_target))
		{
			_alreadyMatched = true;
			action();
		}
		return this;
	}

	public void Default(Action action)
	{
		if (!_alreadyMatched)
		{
			_alreadyMatched = true;
			action();
		}
		return this;
	}
}

Average Rating: 4.6 out of 5 based on 159 user reviews.

Comments (4) Trackbacks (0)
  1. What if you fire the action inside the Case() method instead of storing it? Then you wouldn’t need to call Go() at the end either.

    The Case method could look something like this

    public Switch Case(Predicate @case, Action action)
    {
    if (@case(_target))
    action;
    return this;
    }

    and the Default method would change to

    public Switch Default(Action action)
    {
    action;
    return this;
    }

    and you wouldn’t need the _cases and _default private fields.

  2. I just realized a flaw in my design. If 2 Cases are met, then both actions will be fired instead of only the first case.

    An additional private flag will be needed to keep track if a Case has been met, and that flag will have to be checked before running an action

    public Switch Case(Predicate @case, Action action)
    {
    if(!_caseMet && @case(_target))
    {
    _caseMet = true;
    action;
    }
    return this;
    }

  3. Awesome Idea! Thanks Paul! There is also one more change in behavior. If you specify your Default at some point other than the end of your list of Cases, it’ll catch every time and it will never get to the cases below your Default.

    I’ll update the post with the updated implementation.

  4. Good point about the Default() method bug. Below is such an example:

    int age;
    Switch.On(“Paul”)
    .Case(x => x == “George”, () => { age = 40; })
    .Default( () => { age = 70; })
    .Case(x => x == “Paul”, () => { age = 25; });

    In this situation age would be set to 70 instead of 25.

    I think the Default() method signature will have to be updated to return void instead of Switch. This will ensure that Default() is always at the end of the statement and is only called if none of the Cases have been met.


Leave a comment


No trackbacks yet.