Tuesday, December 27, 2011

Working with enums


Working with enum types is straightforward. We have provided a few core methods to simplify certain operations.

Accessing/creating enum values

An enum type is a value type derived from System.Enum. The named constants in an enum type are implemented as static fields on the type.  For example, System.IO.FileMode, defined in C# as

public enum FileMode
{
    Append = 6,
    Create = 2,
    CreateNew = 1,
    Open = 3,
    OpenOrCreate = 4,
    Truncate = 5
}

has an MSIL implementation more-or-less equivalent to

[Serializable]
public sealed class FileMode : System.Enum
{
    public static System.IO.FileMode CreateNew = 1;
    public static System.IO.FileMode Create = 2;
    public static System.IO.FileMode Open = 3;
    public static System.IO.FileMode OpenOrCreate 4;
    public static System.IO.FileMode Truncate = 5;
    public static System.IO.FileMode Append = 6;
}

Thus, we can use our regular static-field access interop syntax to retrieve these values:

(import 'System.IO.FileMode) ;=> System.IO.FileMode
FileMode/CreateNew           ;=> CreateNew

These are not integral-type values. They retain the enumeration type.

(class FileMode/CreateNew) ;=> System.IO.FileMode

You can convert them to an integer value if you desire:

(int FileMode/CreateNew) ;=> 1

If you want to convert from an integer value to an enumeration value, try:

(Enum/ToObject FileMode 4) ;=> OpenOrCreate

If you want convert from the name of an integer to an enumeration value, the enum-val method will work with strings or anything that name works on:

(enum-val FileMode "CreateNew") ;=> CreateNew
(enum-val FileMode :CreateNew)  ;=> CreateNew


Working with bit fields

Enumeration types that have the Flags attribute are often used to represent bit fields. For convenience, we provide methods bit-or and bit-and to to combine and mask bit field values. For example, System.IO.FileShare has the Flags attribute. It is defined as follows:

[Serializable, ComVisible(true), Flags]
public enum FileShare
{
 Delete = 4,
 Inheritable = 0x10,
 None = 0,
 Read = 1,
 ReadWrite = 3,
 Write = 2
}

Use enum-or to combine values.

(import 'System.IO.FileShare)
(enum-or FileShare/Read FileShare/Write) ;=> ReadWrite

Use enum-and to mask values.

(def r (enum-or FileShare/ReadWrite FileShare/Inheritable))
(= (enum-and r FileShare/Write) FileShare/Write) ;=> true
(= (enum-and r FileShare/Write) FileShare/None)  ;=> false
(= (enum-and r FileShare/Delete) FileShare/None) ;=> true


You can also use the HasFlag method to test if a bit is set:

(.HasFlag r FileShare/Write)  ;=> true
(.HasFlag r FileShare/Delete) ;=> false


No comments:

Post a Comment