1

I'm trying to implement a generic function, Let's say we have Modes & it's corresponding Sub modes enter image description here

Now what I have done was I've created an Enum for Modes

public enum Modes
{
    ModeA,
    ModeB,
    ModeC
}

and similarly for SubModes,

public enum SubModesA
{
    SubModeA1,
    SubModeA2,
    SubModeA3
}

public enum SubModesB
{
    SubModeB1,
    SubModeB2
}

public enum SubModesC
{
    SubModeC1,
    SubModeC2,
    SubModeC3
}

Now my question is, How to implement a Method(it could be a generic) which takes in Mode as one input, Sub Modes as second input, please note that the second input(Sub Modes) has to be based on first input,

(Ex. Public void PerformOperation(Modes mode, SubModes subMode){};

any ideas please?

SanVEE
  • 2,009
  • 5
  • 34
  • 55
  • Do they have to be `enum` types? EDIT: Just to clarify, could they be classes with a fixed set of members (like here: http://stackoverflow.com/questions/2119714/when-to-use-enums-and-when-to-replace-them-with-a-class-with-static-members), or could they be anything else? – Chris Sinclair Sep 25 '14 at 16:51
  • You would be better served for your PerformOperation method to take an interface as a parameter, and then perform the operation on the interface type. That way you don't have to add to the enumeration every time you add a new operation. – Michael G Sep 25 '14 at 16:52
  • Enums would be ideal, as the user could see the corresponding subModes when they type. – SanVEE Sep 25 '14 at 16:52
  • @San': So is this purely about achieving some nice intellisense/API for developers consuming your code? Did you have any other plans (serialization for example?) – Chris Sinclair Sep 25 '14 at 16:53
  • 1
    This sounds like polymorphic behavior, you should use *actual polymorphism* instead of forcing some enum switch. – BradleyDotNET Sep 25 '14 at 16:55
  • @Chris, Yeah I agree at the same time, I want to make sure it's just one method, the other option would be to use multiple functions with different input parameters. – SanVEE Sep 25 '14 at 16:55

2 Answers2

3

You won't be able to get this behavior using an enum for your mode. You'll need to use a mechanism that involves having a different type for each mode, so that each mode can map to a different overload of a method. You can use a class like this to accomplish that:

public class Mode
{
    public static readonly ModeA ModeA = new ModeA();
    public static readonly ModeB ModeA = new ModeB();
    public static readonly ModeC ModeA = new ModeC();
    public class ModeA { }
    public class ModeB { }
    public class ModeC { }
}

Now you can write methods such as this:

public static void PerformOperation(Mode.ModeA mode, SubModesA subMode)
{

}

You can create methods for each type of mode, each having the appropriate sub mode. This means that a caller can now write:

PerformOperation(Mode.ModeA, 

and the only valid values for the second parameter are instances of the appropriate submode.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Thanks Servy, Interesting one but Not sure if I understand this one though. – SanVEE Sep 25 '14 at 17:03
  • @San' What don't you understand? – Servy Sep 25 '14 at 17:06
  • It's clear now, the thing that I didn't understand was `SubModesA` parameter in `PerformOperation()` method, later I realized it's the Enum. This is pretty much similar to having three methods, from which the first input Parameter is same (`Modes`) for all the methods, and the second parameter can be different. – SanVEE Sep 26 '14 at 09:16
2

With your current structure, this is not possible. Generic type constraints are pretty limited in what they allow you to constrain. Effectively, you can restrict to classes (new) and enforce derivation from a class or interface.

If you made the enums objects and the various SubModesA derived from ModeA, and ModeA derive from Mode then you could do:

public class MyGenericClass<T,U> where T : Mode
                                 where U : T

You may want to consider a number of other patterns (template method, strategy come to mind) in order to handle this case.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117