/// <summary>
        /// Determines wheter the specified block is part of the state machine controller.
        /// </summary>
        /// <remarks>
        /// We look for this pattern:
        /// ...
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// beq* stateEntry
        /// 
        /// or
        /// 
        /// ....
        /// ldloc.* stateVariable
        /// (ldc.i4.* stateNumber) - can be missing
        /// (sub)                  - can be missing
        /// switch ....
        /// 
        /// or
        /// 
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// bnq* default
        /// stateEntry:
        /// .........
        /// 
        /// or
        /// 
        /// ldfld stateField
        /// ldc.i4.* stateNumber
        /// ceq
        /// ldc.i4.0
        /// .....
        /// brtrue* default
        /// stateEntry:
        /// ............
        /// 
        /// In some cases there is no state variable. Instead the state field is loaded.
        /// 
        /// Update:
        /// Since C#6.0 this case is added:
        /// 
        /// ...
        /// ldloc.1
        /// brfalse.s IL_0012
        /// ...
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <param name="stateNumber"></param>
        /// <returns>False if the specified block is not part of the state machine controler, true - otherwise.</returns>
        private bool IsStateMachineControllerBlock(ref InstructionBlock theBlock, out StateMachineControllerType controllerType, out int stateNumber)
        {
            theBlock = SkipBranchChain(theBlock);

            Instruction currentInstruction = theBlock.Last;

            if (theCFG.SwitchBlocksInformation.ContainsKey(theBlock))
            {
                controllerType = StateMachineControllerType.Switch;

                if (currentInstruction.Previous.OpCode.Code == Code.Sub || currentInstruction.Previous.OpCode.Code == Code.Sub_Ovf)
                {
                    currentInstruction = currentInstruction.Previous.Previous;
                    if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                    {
                        return false;
                    }
                }
                else
                {
                    stateNumber = 0;
                }
            }
            else if (IsBeqInstruction(theBlock.Last)) //controllerType == StateMachineControllerType.Conditions
            {
                controllerType = StateMachineControllerType.Condition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return false;
                }
            }
            else if (IsBrFalseInstruction(theBlock.Last))
            {
                controllerType = StateMachineControllerType.Condition;

                currentInstruction = theBlock.Last;
                stateNumber = 0;
            }
            else if (IsBneInstruction(theBlock.Last))
            {
                controllerType = StateMachineControllerType.NegativeCondition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return false;
                }
            }
            else if (IsDebugControllerBlock(theBlock, out stateNumber))
            {
                controllerType = StateMachineControllerType.NegativeCondition;
                return true;
            }
            else
            {
                controllerType = StateMachineControllerType.None;
                stateNumber = 0;
                return false;
            }

            VariableReference varReference;
            if (ContainsStateFieldLoad(theBlock) ||
                TryGetVariableFromInstruction(currentInstruction.Previous, out varReference) && varReference == stateVariable &&
                !ContainsStateVariableSet(theBlock))
                //In rare cases the state variable is used in a regular switch block. That's why we check whether there is an assignment of the variable
                //in theBlock. If so then the block is not a controller block.
            {
                return true;
            }

            stateNumber = 0;
            return false;
        }
        /// <summary>
        /// Determines wheter the specified block is part of the state machine controller.
        /// </summary>
        /// <remarks>
        /// We look for this pattern:
        /// ...
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// beq* stateEntry
        ///
        /// or
        ///
        /// ....
        /// ldloc.* stateVariable
        /// (ldc.i4.* stateNumber) - can be missing
        /// (sub)                  - can be missing
        /// switch ....
        ///
        /// or
        ///
        /// ldloc.* stateVariable
        /// ldc.i4.* stateNumber
        /// bnq* default
        /// stateEntry:
        /// .........
        ///
        /// or
        ///
        /// ldfld stateField
        /// ldc.i4.* stateNumber
        /// ceq
        /// ldc.i4.0
        /// .....
        /// brtrue* default
        /// stateEntry:
        /// ............
        ///
        /// In some cases there is no state variable. Instead the state field is loaded.
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <param name="stateNumber"></param>
        /// <returns>False if the specified block is not part of the state machine controler, true - otherwise.</returns>
        private bool IsStateMachineControllerBlock(ref InstructionBlock theBlock, out StateMachineControllerType controllerType, out int stateNumber)
        {
            theBlock = SkipBranchChain(theBlock);

            Instruction currentInstruction = theBlock.Last;

            if (theCFG.SwitchBlocksInformation.ContainsKey(theBlock))
            {
                controllerType = StateMachineControllerType.Switch;

                if (currentInstruction.Previous.OpCode.Code == Code.Sub || currentInstruction.Previous.OpCode.Code == Code.Sub_Ovf)
                {
                    currentInstruction = currentInstruction.Previous.Previous;
                    if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                    {
                        return(false);
                    }
                }
                else
                {
                    stateNumber = 0;
                }
            }
            else if (IsBeqInstruction(theBlock.Last)) //controllerType == StateMachineControllerType.Conditions
            {
                controllerType = StateMachineControllerType.Condition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return(false);
                }
            }
            else if (IsBneInstruction(theBlock.Last))
            {
                controllerType = StateMachineControllerType.NegativeCondition;

                currentInstruction = theBlock.Last.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateNumber))
                {
                    return(false);
                }
            }
            else if (IsDebugControllerBlock(theBlock, out stateNumber))
            {
                controllerType = StateMachineControllerType.NegativeCondition;
                return(true);
            }
            else
            {
                controllerType = StateMachineControllerType.None;
                stateNumber    = 0;
                return(false);
            }

            VariableReference varReference;

            if (ContainsStateFieldLoad(theBlock) ||
                TryGetVariableFromInstruction(currentInstruction.Previous, out varReference) && varReference == stateVariable &&
                !ContainsStateVariableSet(theBlock))
            //In rare cases the state variable is used in a regular switch block. That's why we check whether there is an assignment of the variable
            //in theBlock. If so then the block is not a controller block.
            {
                return(true);
            }

            stateNumber = 0;
            return(false);
        }