**Yes, it's do-able, and may be a good idea**

Certainly this is doable, and it can often yield clearer logic, depending on what parameters you are using. Hopefully the parameters are related in some way that ties into a well-understood business concept.

**Identify the hidden business concept**

In cases where the two parameters map to a single (hidden) business concept, you need to make that concept explicit, using a mapping function that takes `p` and `q` and outputs the case.

This example corresponds to your first example:

 z = map(p, q)
 switch (z)
 case z1:
 a();
 break;
 case z2:
 b();
 break;
 case z3:
 c();
 break;
 case z4:
 d();
 break;
 }

Or for your second example:

 z = map(p, q)
 switch (z)
 case z1:
 a();
 break;
 case z2:
 a();
 b();
 break;
 case z3:
 c();
 break;
 case z4:
 //No operation
 break;
 }

**What is the mapping function?**

The mapping function can be as simple as combining `p` and `q` into a bitmask (if they are Booleans) or combining strings (if they are, for example, product and subproduct codes). This could be a stretch in some circumstances, but is a plain and obvious solution in other circumstances. For example, consider these questions that may appear on an application for health insurance:

1. Are you married? Yes or no
2. Do you have children? Yes or no

In this case, your company might offer four products (the hidden business concept): single, married, single with children, and married with children. In this sort of scenario it is perfectly justified to combine the user's answers into a virtual product (given by the mapping function) and choosing a logic path based on the product instead of the individual flags. In fact it is much better code, IMO.

**Getting rid of the switch case**

Switch/case is ugly. Another approach would continue to use the hidden business concept but in a cleaner code pattern:

 IProduct z = ProductFactory.GetProduct(q, p);
 z.Execute();

...where the factory could return one of four products, all of which implement `IProduct` which contains a product-specific `Execute` method that will execute `a()`, `b()`, `c()`, and/or `d()` as needed. 

**Won't the factory have the same (original) issue?**

The factory could contain nested `if` statements (bringing back the original problem) or it could use a lookup table for instantiation, like this:

 class ProductFactory
 {
 private static readonly Dictionary<bool, Dictionary<bool, Func<IProduct>>> _products 
 = new Dictionary<bool, Dictionary<bool, Func<IProduct>>>();

 static ProductFactory()
 {
 _products.Add(false, new Dictionary<bool, Func<IProduct>> {
 { true, () => new ProductSingleWithChildren() },
 { false, () => new ProductSingle() }
 });
 _products.Add(true, new Dictionary<bool, Func<IProduct>> {
 { true, () => new ProductMarriedWithChildren() },
 { false, () => new ProductMarried() }
 });

 }
 public IProduct GetProduct(bool isMarried, bool hasChildren)
 {
 return _products[isMarried][hasChildren]();
 }
 }

...where `_products` is a list of lists, each item containing a `Func<IProduct>` that will instantiate the appropriate type. 

Dictionaries with a key of `bool` seem a little weird, so in an actual piece of code you might lean toward using an `enum` instead, or possible a `string` containing a code. I would suggest using an identifier that is aligned with the business/domain; make it easy for other developers to understand what is going on. 

For completeness, here is an idea what the classes would look like:

 interface IProduct
 {
 void Execute();
 }
 class ProductSingle : IProduct
 {
 public void Execute()
 {
 a();
 }
 }
 class ProductSingleWithChildren : IProduct 
 {
 public void Execute()
 {
 a();
 b();
 }
 }
 class ProductMarried: IProduct 
 {
 public void Execute()
 {
 c();
 }
 }
 class ProductMarriedWithChildren : IProduct 
 {
 public void Execute()
 {
 //No operation
 }
 }

You'll notice in the end we not only got rid of the duplicate `if` condition, there are in fact ZERO `if` statements in the whole solution!!! :) Pretty neat, and will get you a low cyclomatic complexity score and a nice clean CPU pipeline. Plus much more readable code.

Then again, we just wrote a LOT more lines of code than the original example. So, depending on context, maybe the nested `if` statements would be better, in certain cases, e.g. the combination of the flags is arbitrary or doesn't map to a logical concept within the business problem, or the extra readability isn't necessary for a certain small problem. It's up to you, of course.