Showing posts with label enum. Show all posts
Showing posts with label enum. Show all posts

October 16, 2023

Bit Operations

An extension class that allows various bitwise operations on an integer to be performed when dealing with a [Flags] Enum type.

// Bit wise operations on an integer as an extensions class
public static class IntBitwiseOperationsExtender
{
    // Returns bits set in lhs or rhs or both
    public static int BitwiseUnion(this int lhs, int rhs)
    {
        int bitWiseOr = lhs | rhs;
        return bitWiseOr;
    }

    // Return bits set common to both lhs and rhs
    public static int BitwiseIntersection(this int lhs, int rhs)
    {
        return lhs & rhs;
    }

    // Returns bits set in lhs or rhs but not in both
    public static int BitwiseExclusiveOr(this int lhs, int rhs)
    {
        int exclusiveOr = BitwiseUnion(lhs, rhs) - BitwiseIntersection(lhs, rhs);
        return exclusiveOr;
    }

    // Return lhs bits inverted, 0s becomes 1s and vice versa
    public static int BitwiseInvert(this int lhs)
    {
        int bitWiseOr = ~lhs;
        return bitWiseOr;
    }

    // Return lhs bits set minus any that are also set in the rhs
    public static int BitwiseRemove(this int lhs, int rhs)
    {
        int common = BitwiseIntersection(lhs, rhs); // Find the bits common to both sides
        int res = (int)lhs - (int)common;
        return res;
    }

    // Return a value that has all the bits set either in the lhs part or in the rhs part or both
    public static int BitwiseOr(this int lhs, int rhs)
    {
        return BitwiseUnion(lhs, rhs); // Same as a Bitwise Union
    }

    // Return true if lhs contains all the bits set within rhs
    public static bool BitwiseContains(this int lhs, int rhs)
    {
        int common = lhs & rhs;
        return (common == rhs);
    }

    // Return true if lhs contains one of the bits set within rhs
    public static bool BitwiseContainsOneOf(this int lhs, int rhs)
    {
        int common = lhs & rhs;
        return common > 0;
    }
}

March 2, 2017

Thread Safe Enum Access Using Interlocked

Here is an example class that makes reading and writing an enum property thread safe (when writing or reading the enum value)
/// <summary>
///     A thread safe MyEnum.
/// </summary>
public class ThreadSafeMyEnum
{
 // Volatile is not needed (esp. on x64 or x86) : 
 // http://stackoverflow.com/questions/7177169/how-to-apply-interlocked-exchange-for-enum-types-in-c 
 // http://stackoverflow.com/questions/425132/a-reference-to-a-volatile-field-will-not-be-treated-as-volatile-implications
 private int _enumAsInt;

 public MyEnum Value // added for convenience
 {
  get { return ( MyEnum ) Interlocked.CompareExchange( ref _enumAsInt, 0, 0 ); }
  set { Interlocked.Exchange( ref _enumAsInt, ( int ) value ); }
 }
}

August 23, 2011

Enum and Description Attribute

Found this helper in this article EnumHelper - Getting a Friendly Description from an Enum by Grant Barrington, initially.
Found idea for the generic enum class here
Have refactored and merged them a little and added a couple of my own methods
    /// <summary>
    /// Not really an extension class but this is more readable than an extension class.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class Enum<T> 
        where T : struct, Enum
    {
        /// <summary>
        /// Parse the given string into an enum value, ignores the case of the string
        /// </summary>
        /// <param name="value">string to parse, leading and trailing whitespace characters are removed</param>
        /// <returns>Enum value parsed from the string</returns>
        public static T Parse(string value)
        {
            return Enum<T>.Parse(value.Trim(), true);
        }

        /// <summary>
        /// Parse the given string into an enum value
        /// </summary>
        /// <param name="value">string to parse, leading and trailing whitespace characters are removed</param>
        /// <param name="ignoreCase">Whether to ignore the case of the letters in the string when parsing</param>
        /// <returns>Enum value parsed from the string</returns>
        public static T Parse(string value, bool ignoreCase)
        {
            return (T)Enum.Parse(typeof(T), value.Trim(), ignoreCase);
        }

        /// <summary>
        /// Try to parse the given string into an enum value, ignores the case of the string. Capture any exceptions
        /// </summary>
        /// <param name="value">string to parse, leading and trailing whitespace characters are removed</param>
        /// <param name="returnedValue">Enum value parsed from the string</param>
        /// <returns>true if the string was successfully parsed into a enum value of the given type</returns>
        public static bool TryParse(string value, out T returnedValue)
        {
            return Enum.TryParse<T>(value, true, out returnedValue);
        }

        /// <summary>
        /// Try to parse the given string into an enum value. Capture any exceptions
        /// </summary>
        /// <param name="value">string to parse, leading and trailing whitespace characters are removed</param>
        /// <param name="ignoreCase">Whether to ignore the case of the letters in the string when parsing</param>
        /// <param name="returnedValue">Enum value parsed from the string</param>
        /// <returns>true if the string was successfully parsed into a enum value of the given type</returns>
        public static bool TryParse(string value, bool ignoreCase, out T returnedValue)
        {
            return Enum.TryParse<T>(value, ignoreCase, out returnedValue);
        }

        /// <summary>
        /// Get the enum values of the given enum type
        /// </summary>
        /// <returns>Array of the enum values in the enum type</returns>
        public static Array GetValues()
        {
            return Enum.GetValues(typeof(T));
        }

        /// <summary>
        /// Returns first description attribute of the enum value or the enum value 
        /// itself as a string if no description attribute was found
        /// </summary>
        /// <param name="enumValue">An enum value in the given enum type</param>
        /// <returns>
        /// First description attribute found of the enum value or the enum value 
        /// itself as a string if no description attribute was found
        /// </returns>
        public static string GetAsString(T enumValue)
        {
            string res = GetFirstDescriptionAttribute(enumValue);
            if (string.IsNullOrEmpty(res))
                res = enumValue.ToString();
            return res;
        }

        /// <summary>
        /// Returns first description attribute of the enum value
        /// </summary>
        /// <param name="enumValue">An enum value in the given enum type</param>
        /// <returns>
        /// First description attribute found of the enum value or null if no description attribute was found
        /// </returns>
        public static string GetDescriptionAttribute(T enumValue)
        {
            Type type = enumValue.GetType();

            MemberInfo[] memInfo = type.GetMember(enumValue.ToString());

            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(
                    typeof(DescriptionAttribute), false);

                if (attrs != null && attrs.Length > 0)
                {
                    return ((DescriptionAttribute)attrs[0]).Description;
                }
            }

            return null;
        }

 
    }
Now use the above helpers to demonstrate how to get the description attribute on an enum entry and how to get the best string form for an enum for entry into a listbox or something
public enum DescriptionsEnum
{
    [DescriptionAttribute("Add On")]
    AddOn,
    [DescriptionAttribute("Snap On")]
    SnapOn = 7,
    Adjacent = 2,
    Fixed = 12,
};

public void Test1()
{
    int asInt = 0;            
    foreach (var entry in Enum<DescriptionsEnum>.GetValues())
    {
        asInt = (int)entry;
        Console.WriteLine(asInt.ToString() + " " + 
            entry.ToString() + ":" + 
            Enum<DescriptionsEnum>.GetDescriptionAttribute((Enum)entry));
    }
    Console.WriteLine();
    foreach (var entry in Enum<DescriptionsEnum>.GetValues())
    {
        asInt = (int)entry;
        Console.WriteLine(asInt.ToString() + " " + 
            Enum<DescriptionsEnum>.GetAsString((Enum)entry));
    }
}
and the output of the test is
0 AddOn:Add On
2 Adjacent:
7 SnapOn:Snap On
12 Fixed:

0 Add On
2 Adjacent
7 Snap On
12 Fixed
There is also an interesting article on Enum: Binding to the Description Attribute by Deborah Kurata.
Using these helpers making something to bind to is much simpler:
Dictionary<string, int> bindToMe = new Dictionary<string, int>();
foreach (var entry in Enum.GetValues(typeof(DescriptionsEnum)))
{
    asInt = (int)entry;
    bindToMe.Add(EnumHelper.GetAsString((Enum)entry), asInt);
} 

August 11, 2011

Enum type information in C++/CLI

Testing a generic parameter for enum type information
generic <class TValue>
...MyMethod()
{
  // Testing a generic parameter for enum type information
  
  System::Type^ enumType = TValue::typeid;
  // Only enum types supported
  if (!enumType->IsEnum) 
  {
    throw gcnew System::ArgumentException("...");
  }
  // Only 32 bit integer enum types are supported
  if (System::Enum::GetUnderlyingType(enumType) != System::Int32::typeid) 
  { 
    throw gcnew System::ArgumentException("...");
  }
  // [Flags] type enums not supported
  array<System::Object^>^ attributes = enumType->
    GetCustomAttributes(System::FlagsAttribute::typeid, false);
  if (attributes->Length != 0) 
  {
    throw gcnew System::ArgumentException("...");
  }
}

August 16, 2008

Enums

See this blog entry for information and example on the use of DescriptionAttribute with Enums

This example uses an ComboBox to store the enumeration values as strings Preparing the Combobox
foreach (XXXEnum entry in Enum.GetValues(typeof(XXXEnum)))
    comboBox.Items.Add(entry);
OR
cbLoggingLevel.Items.AddRange(Enum.GetValues(typeof(XXXEnum)));

// Making an initial selection
comboBox.SelectedIndex = comboBox.Items.Count - 1; // Select the last one
OR
comboBox.SelectedIndex = 0; // Select the first
Converting to and from a string
//To convert an enum to a string use:
MyComboBox.SelectedItem = m_Object.XXXEnum .ToString();

//The reverse process is a little more complicated
XXXEnum gc = (XXXEnum ) Enum.Parse(typeof(XXXEnum ),
                        MyComboBox.SelectedItem.ToString(), true);
There is a better way to parse the enum from a string that I found here.:
public static class StringExtender
{
  public static TEnum ParseToEnum<TEnum>(this string name)
    where TEnum : struct
  {
    if (false == typeof(TEnum).IsEnum)
      throw new NotSupportedException(typeof(TEnum).Name + " must be an Enum");

    string trimmed = name.Trim();
    
    if (false == Enum.IsDefined(typeof(TEnum), trimmed))
      throw new ArgumentException(string.Format(
         "\'{0}\' is not defined in type of enum {1}", trimmed, typeof(TEnum).Name));

    return (TEnum)Enum.Parse(typeof(TEnum), trimmed);
  }
}
alternatively use the TryParse method.
public class EnumTester
{
  public enum DescriptionsEnum
  {
    None,
    AddOn,
    SnapOn,
    Adjacent,
    Fixed,
  };

  public void ParseEnumFromStringTest()
  {
    DescriptionsEnum test = DescriptionsEnum.None;
    test = StringExtender.ParseToEnum<DescriptionsEnum>("Adjacent");
    Debug.Assert(test == DescriptionsEnum.Adjacent);
    test = "Fixed".ParseToEnum<DescriptionsEnum>();
    Debug.Assert(test == DescriptionsEnum.Fixed);
    test = "   SnapOn  ".ParseToEnum<DescriptionsEnum>();
    Debug.Assert(test == DescriptionsEnum.SnapOn);
    //test = "      snapon    ".ParseToEnum<DescriptionsEnum>(); // FAILS!
    //Debug.Assert(test == DescriptionsEnum.SnapOn);

    bool success = Enum.TryParse<DescriptionsEnum>("Adjacent", out test);
    Debug.Assert(test == DescriptionsEnum.Adjacent);
    success = Enum.TryParse<DescriptionsEnum>("fixed", true, out test);
    Debug.Assert(test == DescriptionsEnum.Fixed);
    success = Enum.TryParse<DescriptionsEnum>("  fixed     ", true, out test);
    // Line below succeeds. - TryParse is more robust so use it instead!
    Debug.Assert(test == DescriptionsEnum.Fixed); 
  }
}

Iterating through enumerated types:
foreach (XXXEnum entry in Enum.GetValues(typeof(XXXEnum)))
{
    Debug.WriteLine(entry.ToString() + "=" + ((int)entry).ToString());                
}
See Flags Based Enumerated Types

November 25, 2007

Flags Based Enumerated Types

An extension class that extends a flag based enumerated type with set/group theory type operations. See FileAttributesExtender for a usage of this class.
public partial class EnumFlagsForm : Form
{
    [Flags]
    public enum EnumFlags
    {
        None = 0,
        Emergency_Stop = 0x1,
        Greasey = 0x2,
        Spot_Spot = 0x4,
        Doughnuts = 0x8,
        Lift_Moving = 0x10,
        Doors_Open = 0x20,
        Forbidden = 0x40
    }

//SourceTypes sourceTypes;
public static class EnumFlagsExtender
{
 // Return lhs flags plus rhs flags
 public static EnumFlags Union(this EnumFlags lhs, EnumFlags rhs)
 {
  return lhs | rhs;
 }

 // Return flags common to lhs and rhs
 public static EnumFlags Intersection(this EnumFlags lhs, EnumFlags rhs)
 {
  return lhs & rhs;
 }

 // Return lhs flags minus rhs flags
 public static EnumFlags Subtract(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  int res = (int)lhs - (int)common;
  return (EnumFlags)(res);
 }

 // Return true if lhs contains all the flags within rhs
 public static bool Contains(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  return (common == rhs);
 }

 // Return true if lhs contains one of the flags within rhs
 public static bool ContainsOneOf(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  return ((int)common > 0);
 }

 
 // NON-extension methods here

 public static EnumFlags FromString(string source)
 {
  EnumFlags res = (EnumFlags)Enum.Parse(typeof(EnumFlags), source, true);
  return res;
 }

    }

    public void Test1()
    {
      EnumFlags test = EnumFlags.Lift_Moving |
          EnumFlags.Doors_Open | EnumFlags.Doughnuts;
      string str = test.ToString();
      //str = str.Replace('_', ' ');
      Debug.WriteLine(str);
      EnumFlags newtest = EnumFlagsExtender.FromString(str);
      Debug.Assert(newtest == test);      
    }

public void EnumFlagsSubtractTest()
{
    EnumFlags test1 = EnumFlags.Lift_Moving | EnumFlags.Doors_Open |
        EnumFlags.Doughnuts | EnumFlags.Emergency_Stop;
    EnumFlags test2 = EnumFlags.Lift_Moving | EnumFlags.Forbidden |
        EnumFlags.Emergency_Stop;
    EnumFlags expected = EnumFlags.Doors_Open | EnumFlags.Doughnuts;
    EnumFlags outcome = test1.Subtract(test2);
    Debug.Assert(outcome == expected);

    expected = EnumFlags.Doors_Open | EnumFlags.Doughnuts | EnumFlags.Greasey;
    outcome = outcome.Union(EnumFlags.Greasey);
    Debug.Assert(outcome == expected);

    EnumFlags test3 = EnumFlags.Doughnuts | EnumFlags.Greasey;
    bool res = outcome.Contains(test3);
    Debug.Assert(res);
    
    res = outcome.Contains(EnumFlags.Lift_Moving | EnumFlags.Forbidden);
    Debug.Assert(!res);
}


    public EnumFlagsForm()
    {
        InitializeComponent();
        lbSourceTypes.Items.AddRange(
UnderscoresToSpaces(
Enum.GetNames(typeof(EnumFlags))));
        OnSelectedValueChanged(this, null);
    }

    string[] UnderscoresToSpaces(string[] src)
    {
        return ReplaceInStrings('_', ' ', src);
    }

    string[] SpacesToUnderscores(string[] src)
    {
        return ReplaceInStrings('_', ' ', src);
    }

    string SpacesToUnderscores(string src)
    {
        return src.Replace(' ', '_');
    }

    string[] ReplaceInStrings(char oldchar, char newchar, params string[] src)
    {
        string[] res = new string[src.Length];
        int ix = 0;
        foreach (string targ in src)
        {
            res[ix++] = targ.Replace(oldchar, newchar);
        }
        return res;
    }


    private void OnSelectedValueChanged(object sender, EventArgs e)
    {
        EnumFlags test = EnumFlags.None;
        foreach (string type in lbSourceTypes.SelectedItems)
        {
            test = EnumFlagsHelper.Add(test, 
EnumFlagsHelper.FromString(SpacesToUnderscores(type)));
        }
        tbSelected.Text = test.ToString();
        lblIsAudioAndVideo.Text = "WoopsTest() == " + 
(EnumFlagsHelper.WoopsTest(test)).ToString();
    }

    private void butTest_Click(object sender, EventArgs e)
    {
        Test1();
 
        EnumFlagsSubtractTest();
    }

}
Here is a visual studio code snippet for the enum extender
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
     <CodeSnippet Format="1.0.0">
          <Header><Title>Flags Enum Extender pattern</Title>
               <Description>Implement an extender for a 'Flags' type Enum. The extender adds set type methods to the enumertaion type</Description>
               <Keywords>
                   <Keyword>Enum</Keyword>
              </Keywords>
              <Author>Roger Bovill</Author>
         </Header>
         <Snippet>
         <Declarations> 
              <Literal Editable="true">
          <ID>EnumName</ID>
          <ToolTip>Name of the '[Flags]' based enumerated type</ToolTip>
    <Default>MyEnumType</Default>  
                <Function></Function>
             </Literal>
        </Declarations>
        <Code Language="CSharp">
            <![CDATA[

#region $EnumName$Extender

    public static class $EnumName$Extender
    {
        // Return lhs flags plus rhs flags
        public static $EnumName$ Union(this $EnumName$ lhs, $EnumName$ rhs)
        {
            return lhs | rhs;
        }

        // Return flags common to lhs and rhs
        public static $EnumName$ Intersection(this $EnumName$ lhs, $EnumName$ rhs)
        {
            return lhs & rhs;
        }

        // Return lhs flags minus rhs flags
        public static $EnumName$ Subtract(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            int res = (int)lhs - (int)common;
            return ($EnumName$)(res);
        }

        // Return true if lhs contains all the flags within rhs
        public static bool Contains(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            return (common == rhs);
        }

        // Return true if lhs contains one of the flags within rhs
        public static bool ContainsAnyOf(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            return ((int)common > 0);
        }

        // NON-extension methods here

        public static $EnumName$ FromString(string source)
        {
            $EnumName$ res = ($EnumName$)Enum.Parse(typeof($EnumName$), source, true);
            return res;
        }

    }

#endregion $EnumName$Extender

            ]]>
        </Code>
       </Snippet>
    </CodeSnippet>
</CodeSnippets>

July 14, 2005

Using Flag based Enumerated Types


class EnumSample
{
#region ControlData

/// <summary>
/// Flag based enumerated type
/// </summary>
[Flags]
private enum ControlData
{
 /// <summary>
 /// No data of any kind available
 /// </summary>
 None = 0,
 /// <summary>
 /// Hist graph data is available
 /// </summary>
 Hist = 1,
 /// <summary>
 /// Curve graph data is available
 /// </summary>
 Curve = 2,
 /// <summary>
 /// XXX data is available
 /// </summary>
 XXX = 4
}


/// <summary>
/// Record what data is available for the viewer
/// </summary>
private ControlData m_ControlData = ControlData.None;

/// <summary>
/// Is the given Data Available
/// </summary>
/// <param name="datatype">Type of data required</param>
/// <returns></returns>
public bool IsDataAvailable(ControlData datatype)
{
  return ((m_ControlData & datatype) != ControlData.None);
}

/// <summary>
/// Add the given Data Available
/// </summary>
/// <param name="datatype">Type of data now available</param>
public void AddDataAvailable(ControlData value)
{
  m_ControlData |= value;
}

#endregion ControlData
}