|
||
|
|||||||
| C# C# Discussion |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 (permalink) |
|
Forum Expert
|
Enum data type, FLAGS, and Bitwise operations explained. (hopefully)
TUTORIAL LEVEL: Intermediate. Enum: Description: A strongly typed collection of keywords, representing constants of any simple data type, except string. Examples: Code:
public enum MyIntegerEnum
{
One = 1, Two = 2, Three = 3, Four = 4
}
public enum MyDoubleEnum
{
One = 1.0, Two = 2.0, Three = 3.0, Four = 4.0
}
MyIntegerEnum.One MyIntegerEnum.Two etc. Conversions between an enum and it's integral type need to be "cast" explicitly. Code:
int testInteger = (int)MyIntegerEnum.One; If you declare an enum without specifying the values, it is assumed the values are integers. The values are also assumed to increment by '1' in order of how they are displayed. (NOT necessarily in alphabetical order!) This is very important, since you can declare them out of alphabetical sequence, but when you see them displayed in a list, such as within Visual Studio's Context-Sensitive help, it displays them in alphabetical order. Example: Code:
public enum Shapes
{
Circle, Square, Triangle, Octagon, Pentagon
}
Flags: Description: Flags is an Attribute you can assign to an enum. It lets the compiler know that the enum contains values which can be operated on using Bitwise notation. These are important, since it allows you to assign multiple values to a single variable. Here's how it works: When you declare a 'Flags'-variety of the enum data type, you will usually declare them using the hexadecimal integers beginning with 0x0 or 0x1. The number of zeros immediately after the 'x' does not matter, but you should use as many as you need to visually distinguish the numbers. For example, 0x1 and 0x01 are both equal to '1', but 0x10 is not. 0x10 is the hex value '10' or the decimal value '16'. By adding leading zeros, we can line up the numbers visually, so that their values are easier to view and compare. For example: Code:
[FLAGS]
public enum MyFlags
{
FirstFlag = 0x00001,
NextFlag = 0x00002,
AnotherFlag = 0x00004,
FourthFlag = 0x00008,
FifthFlag = 0x00010,
LastFlag = 0x00020
}
Code:
private MyFlags m_Flags = MyFlags.FirstFlag | MyFlags.FourthFlag | MyFlags.LastFlag; Bitwise operations: Bits are zeros and ones. A '0' (Zero) represents 'off' or 'false', and a '1' (One) represents 'on' or 'true'. When displayed as a single series of numbers, each 'Bit' actually represents a much different number than either '0' or '1'. For example, the number 00101001 is equal to the decimal number '41'. Here is how we figure that out: Code:
Value 128 64 32 16 8 4 2 1 Variable 0 0 1 0 1 0 0 1 So, what does this have to do with our 'MyFlags' enum? Well, the values we used are actually the same. 0x00029 is equal to (decimal) 41. Here is the table displayed using Hexadecimal numbers: Code:
Value 0x00080 0x00040 0x00020 0x00010 0x00008 0x00004 0x00002 0x00001 Variable 0 0 1 0 1 0 0 1 To understand bitwise operations, we need to display the bits again, this time separately: Code:
Value 128 64 32 16 8 4 2 1 FirstFlag 0 0 0 0 0 0 0 1 FourthFlag 0 0 0 0 1 0 0 0 LastFlag 0 0 1 0 0 0 0 0 Code:
VALUE 128 64 32 16 8 4 2 1 FirstFlag false false false false false false false true FourthFlag false false false false true false false false LastFlag false false true false false false false false What is the answer to this: false OR false OR false. Of course, the answer is 'false'. How about the '32' column? 'false' OR 'false' OR 'true'. Well, the 'OR' operator says that if any of the values is true, the whole statement is true. So, the '32' column results in 'true'. The same is true for the '8' and '1' columns. What about the bitwise 'AND' operator ('&')? The '&' operator uses logical 'AND' to compare two or more values. If we were to apply this to our Flags, we could evaluate the existence of a particular flag or set of flags in a variable. For example, to see if MyFlags.FourthFlag can be found in m_Flags, we use the '&' operator like this: Here we show our test variable m_Flags, along with the constant FourthFlag. Code:
Value 128 64 32 16 8 4 2 1 m_Flags 0 0 1 0 1 0 0 1 FourthFlag 0 0 0 0 1 0 0 0 Code:
VALUE 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true FourthFlag false false false false true false false false Code:
false AND false = false false AND true = false true AND true = true true AND false = false Code:
VALUE 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true AnotherFlag false false false false false true false false One more operator I want to explain is the '~' (complement) operator. Basically, it inverts all values in a number. So, the complement of 'true' is 'false', and vice versa. Here is how it would look with our variable 'm_Flags': Code:
VALUE 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true ~m_Flags true true false true false true true false Code:
VALUE 128 64 32 16 8 4 2 1 FourthFlag false false false false true false false false ~FourthFlag true true true true false true true true Code:
m_Flags = m_Flags | MyFlags.AnotherFlag; There are other Bitwise operators, such as the Shift '>>' and '<<' operators, but the ones I have explained so far are sufficient for this tutorial. Let's see how this is used in a well-known RunUO script: PlayerMobile.cs: Code:
public bool GetFlag( PlayerFlag flag )
{
return ( (m_Flags & flag) != 0 );
}
public void SetFlag( PlayerFlag flag, bool value )
{
if ( value )
m_Flags |= flag;
else
m_Flags &= ~flag;
}
If the value exists in m_Flags, we can find that by calling the 'GetFlag' method. What the 'return' line says is this: if m_Flags 'AND' the flag we are looking for result in a '0' value, then return false, otherwise, return true. Remember we saw this before in our test when we were looking for 'AnotherFlag' in our variable: Code:
VALUE 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true AnotherFlag false false false false false true false false In the SetFlag method, we have 2 possible statements, 'if (value)' and 'else'; or in other words, if the value we are setting is 'true' then "we run the first statement" else "we run the second statement." Let's look at each statement. Code:
m_Flags |= flag; Code:
m_Flags = m_Flags | flag; But what about the other statement? Code:
m_Flags &= ~flag; Code:
m_Flags = m_Flags & ~flag; Code:
& operation 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true ~flag (~4) true true true true true false true true result: --> false false true false true false false true Code:
& operation 128 64 32 16 8 4 2 1 m_Flags false false true false true false false true ~flag (~8) true true true true false true true true result: --> false false true false false false false true |
|
|
|
![]() |
| Bookmarks |
| Tags |
| bitwise, enum, flags |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|