0

I have an application that use binary/hex a lot to determine if settings are enabled or not. This is probably common practice but I'm new to programming so I wont know.

Setting 1 = 1
Setting 2 = 2
Setting 3 = 4

The number reported in the database would be a total of all the enabled settings, e.g. 7. The implies that all three settings must be enabled as the sum equals 7.

I've made a tuple to report if the respective setting is enabled/disabled.

    public static Tuple<int, string, string, string, string> mytuple(int value)
    {
        switch (value.ToString())
        {
            case "1":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Disabled", "Disabled", "Enabled");
            case "2":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Disabled", "Enabled", "Disabled");
            case "3":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Disabled", "Enabled", "Enabled");
            case "4":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Enabled", "Disabled", "Disabled");
            case "5":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Enabled", "Disabled", "Enabled");
            case "6":
                return new Tuple<int, string, string, string, string>(value, "Disabled", "Enabled", "Enabled", "Disabled");
            case "7":
        return new Tuple<int, string, string, string, string>(value, "Disabled", "Enabled", "Enabled", "Enabled");              
            case "8":
        return new Tuple<int, string, string, string, string>(value, "Enabled", "Disabled", "Disabled", "Disabled");
        }

        return new Tuple<int, string, string, string, string>(0, "", "", "", "");
    }

My question is, is there a simpler way to do this since its binary and the input value, 7 (binary 111) for instance can only be derived in one way i.e. all 3 settings enabled, or 4 (binary 100) for instance is one enabled rest disabled.

Can one make a method to determine which bits are on / off instead having this giant tuple (the actual one runs up to 2048 so the list if very long).

EDIT

I've reviewed all your suggestions and came up with the following after more googling.

    static bool[] bitreader(int input)
    {
        int value = input;

        BitArray b = new BitArray(new int[] { value });

        bool[] bits = new bool[b.Count];
        b.CopyTo(bits, 0);

        return bits;
    }

    public void getnotitype(int input, out XElement notitype)
    {
        bool[] f = bitreader(input);

        notitype = (new XElement(("NotificationType"),
                (new XElement("NotifyUsingMessengerService", f[12])),
                (new XElement("SendEmail", f[13])),
                (new XElement("RunCustomCommand", f[14])),
                (new XElement("LogEvent", f[15]))));
    }

    public void getnotiact(int input, out XElement notiact)
    {
        bool[] f = bitreader(input);

        notiact = (new XElement(("MessengerEventLog"),
        (new XElement("LoggingEnabled", f[0])),
        (new XElement("Severe", f[1])),
        (new XElement("Warning", f[2])),
        (new XElement("Informational", f[3])),
        (new XElement("NotifyUser", f[5])),
        (new XElement("SendSNMP", f[6])),
        (new XElement("NotifyAdmin", f[7])),
        (new XElement("SendToAudit", f[11]))));
    }

Its working fine, does it look OK?

  • 2
    Please consider editing the title. "Better way to do this" doesn't give a hint of what you're asking. – enkryptor Apr 21 '16 at 10:16
  • 3
    That's an abuse of a tuple. I'd not expose such complext tuples via public methods. You don't know what you'll get. **Use classes instead**. Tuples are good with a short lifetime in a method or via private methods – Tim Schmelter Apr 21 '16 at 10:18
  • better way to do this would be to write a Configuration class which encapsulates all the settings, where each on/off setting is actually a boolean. you would need to write some form of a parser to reconstruct a configuration from an input but this can be rather easy _if_ you have a fixed schema for the translation between numeric values and configuration.settings. tl;dr: use oop, not bean counting. – garglblarg Apr 21 '16 at 10:23
  • @enkryptor if you can please suggest a title I'll gladly update it. I'm not sure how to accurately convey the problem using the correct "programming terms" – Riaan Badenhorst Apr 21 '16 at 10:44

4 Answers4

2

You can use binary conversion and use the output.

int value = 7;
int toBase = 2;

//output is a list of characters with 1's and 0's
var output = Convert.ToString(value, toBase).ToList(); 
// gives you list of true/false
var listOfBools = output.Select(x => x=='1'?true:false); 
// gives you list of enabled/disabled string
var listOfStrings = output.Select(x => x=='1'?"enabled":"disabled");

you can loop through the char in the output to get your enabled or disabled key.

Carbine
  • 7,849
  • 4
  • 30
  • 54
2

I would suggest one of the following two examples:

1. Use flags with an Enum.

What does the [Flags] Enum Attribute mean in C#?

I could write more about Flags here, but the whole Flags-concept is covered pretty good in the link above.

[Flags]
public enum Setting
{
    Setting1 = 1,
    Setting2 = 2,
    Setting3 = 4,
    Setting4 = 8
}

private Setting GetSetting()
{
    Setting foo =  Setting.Setting1 | Setting.Setting2 | Setting.Setting3;
    return foo;
}

2. Use ConfigurationSetting.

Instead of using the Tuple the way you do, you can wrap all the settings in a class instead. By using ConfigurationSection you will also be able to store it in your app/web.config.

public class MySettings : ConfigurationSection
{
    /// <summary>
    /// Some setting description here...
    /// </summary>
    [ConfigurationProperty("setting1",
        DefaultValue = false,
        IsRequired = true)]
    public bool Setting1
    {
        get { return (bool)this["setting1"]; }
    }
}

public class Foo
{
    public static MySettings GetSettings()
    {
        // Load settings from your configuration.
        return ConfigurationManager.GetSection("mySettings") as MySettings;
    }
}

And in your config something like this:

<configSections>
    <section name="mySettings" type="YourNameSpace.MySettings, YourAssembly, Version=1.0.0.0, Culture=neutral"></section>
</configSections>
<mySettings setting1="true" />
Community
  • 1
  • 1
smoksnes
  • 10,509
  • 4
  • 49
  • 74
0

Use a [Flags] enum.

[Flags]
public enum Status
{
    Setting1Enabled = 1,
    Setting2Enabled = 2,
    Setting3Enabled = 4
}

That way you can parse your int to an enum that supports bitwise comparisons.

To convert an Integer to that enum use Enum.Parse()

Status status = Enum.Parse(typeof(Status), value);

And to check a certain value you can just compare it against the respective enum value.

Adwaenyth
  • 2,020
  • 12
  • 24
0

I'd use an Enum for your settings and use bitwise operations to set them and check if the flags are set:

[Flags]
enum MyEnum
{
    Setting1 = 1,
    Setting2 = 2,
    Setting3 = 4,
    Setting4 = 8
}

class Program
{
    static void Main(string[] args)
    {
        var myEnum = MyEnum.Setting1;

        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting1));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting2));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting3));

        myEnum = MyEnum.Setting2;

        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting1));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting2));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting3));

        myEnum = MyEnum.Setting2 | MyEnum.Setting3;

        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting1));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting2));
        Console.WriteLine(myEnum.HasFlag(MyEnum.Setting3));

        Console.ReadLine();
    }
}
DoctorMick
  • 6,703
  • 28
  • 26