简体   繁体   中英

Passing Different Options to a Method

I'm looking for a way to pass different options as a parameter to a method. Let's assume that a user can choose any or all of 6 options or any subset of them. So he could choose all options, only option 1, 2 & 4, only option 1, 3, 5 & 6 etc...

How do I pass this around effectively?

I was thinking of using an Enum since you can do bitwise additions, but I'm missing the next pieces of the puzzle to go from there:

Could my method then become something like:

public void Foo(byte selectedOptions)
{
   // How do I check whether an option has been selected??
   if (selectedOptions >= Option.Whatever) DoThis();
}

So you see I'm kind of stuck on the bitwise comparisons and I wonder if this is even the right way...

What I don't want to do is:

public void Foo(bool option1Selected, bool option2Selected, etc...);

Ideas?

Go with enum Flags

[Flags]
public enum FlagTest
{
    None = 0x0,
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4
}

For selecting multiple options use bitwise or

FlagTest testItem = FlagTest.Flag1 | FlagTest.Flag2;

To check if a flag is selected use bitwise and

if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
{
     // Do something
}

User params keyword:

public void Foo(params string[] options);

then you can pass unlimited string params to the function, and read them in the string[] array.

Or using enum(which IMHO is the better way):

[Flags]
public enum MyEnum {
    Value1 = 1,
    Value2 = 2,
    Value3 = 4,
    Value4 = 8,
    Value5 = 16,
    Value6 = 32,
}
public void Foo(MyEnum value){
    if (value & MyEnum.Value1 > 0){
        // we have Value1 passed
    }
}

and call this as:

Foo(MyEnum.Value1 | MyEnum.Value4 | MyEnum.Value10);

Enum values should not be sequential - like 1,2,3,4,5, but flag values - 2^x.

You want to AND your flags

public void Foo(Option selectedOptions) 
{
  if ((selectedOptions & Option.Whatever)>0) 
  {
     // whatever
  }
}

You also should decorate your enum with [Flags]

eg:

[Flags]
public enum Option

Traditionally there were a couple of ways to achieve what you're describing. The first would be to define a struct:

public class FooOptions
{
    bool Fizz;
    bool Buzz;
    bool Boom;
}

... and then the caller of your method would pass an instance of that with the appropriate fields set to true.

Flag enums were another solution:

public enum FooOptions
{
    Fizz = 1,
    Buzz = 2,
    Boom = 4,
}

... which you'd then test using something like:

if ((options & FooOptions.Fizz) == FooOptions.Fizz) { ... }

Nowadays, however, C# has optional and named parameters, which means your final approach (the one you didn't want to do) would be the most sensible:

public void Foo(bool fizz = false, bool buzz = false, bool boom = false)
{
    ...
}

... which you could then call with any permutation of parameters, like:

Foo(fizz: true, boom: true);
Foo(buzz: true);

You can use HashSet<YourEnum> to hold a set of options.

public void Foo(HashSet<YourEnum> selectedOptions)
{
    if(selectedOptions.Contains(YourEnum.Option1))
        DoSomething();
}

Using just enum is fine but to me Contains() method is more readable way of testing for an option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM