private string PrintArray(int indentLevel, CorDebug.CorArrayValue av, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            var txt = new StringBuilder();

            txt.Append("array [");
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            for (int i = 0; i < dims.Length; ++i)
            {
                if (i != 0)
                {
                    txt.Append(",");
                }
                txt.Append(dims[i]);
            }
            txt.Append("]");

            if (expandDepth > 0 && av.Rank == 1 && av.ElementType != CorElementType.ELEMENT_TYPE_VOID)
            {
                for (int i = 0; i < dims[0]; i++)
                {
                    // Arrays not starting with 0 are not implemented
                    var v = new MDbgValue(Process, av.GetElementAtPosition(i));
                    txt.Append("\n").Append(IndentedString(indentLevel + 1, "[" + i + "] = ")).
                    Append(IndentedBlock(indentLevel + 2,
                                         v.GetStringValue(expandDepth - 1, canDoFunceval)));
                }
            }
            return(txt.ToString());
        }
        /// <summary>
        /// Gets the Array Item for the specified indexes
        /// </summary>
        /// <param name="indexes">Which indexes to get the Array Item for.</param>
        /// <returns>The Value for the given indexes.</returns>
        public MDbgValue GetArrayItem(params int[] indexes)
        {
            if (!IsArrayType)
            {
                throw new MDbgValueException("Type is not array type");
            }

            CorDebug.CorValue      value = Dereference(CorValue);
            CorDebug.CorArrayValue av    = value.CastToArrayValue();
            Debug.Assert(av != null);
            if (av.Rank != indexes.Length)
            {
                throw new MDbgValueException("Invalid number of dimensions.");
            }

            var sb = new StringBuilder("[");

            for (int i = 0; i < indexes.Length; ++i)
            {
                if (i != 0)
                {
                    sb.Append(",");
                }
                sb.Append(indexes[i]);
            }
            sb.Append("]");

            var v = new MDbgValue(Process, sb.ToString(), av.GetElement(indexes));

            return(v);
        }
        /// <summary>
        /// Gets Array Items.  This function can be called only on one dimensional arrays.
        /// </summary>
        /// <returns>An array of the values for the Array Items.</returns>
        public MDbgValue[] GetArrayItems()
        {
            if (!IsArrayType)
            {
                throw new MDbgValueException("Type is not array type");
            }

            CorDebug.CorValue value = Dereference(CorValue);

            CorDebug.CorArrayValue av = value.CastToArrayValue();
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            var al = new ArrayList();

            Debug.Assert(av.Rank == 1);
            for (int i = 0; i < dims[0]; i++)
            {
                var v = new MDbgValue(Process, "[" + i + "]", av.GetElementAtPosition(i));
                al.Add(v);
            }
            return((MDbgValue[])al.ToArray(typeof(MDbgValue)));
        }
        //////////////////////////////////////////////////////////////////////////////////
        //
        // Implementation Part
        //
        //////////////////////////////////////////////////////////////////////////////////

        private string InternalGetValue(int indentLevel, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            CorDebug.CorValue value = CorValue;
            if (value == null)
            {
                return("<N/A>");
            }

            // Record the memory addresses if displaying them is enabled
            string prefix = String.Empty;

            if (m_process.m_engine.Options.ShowAddresses)
            {
                string ptrStr = MakePtrString(value);
                if (!String.IsNullOrEmpty(ptrStr))
                {
                    prefix = "(" + ptrStr + ") ";
                }
            }

            try
            {
                value = Dereference(value);
            }
            catch (COMException ce)
            {
                if (ce.ErrorCode == (int)CorDebug.HResult.CORDBG_E_BAD_REFERENCE_VALUE)
                {
                    return(prefix + "<invalid reference value>");
                }
                throw;
            }

            if (value == null)
            {
                return(prefix + "<null>");
            }

            Unbox(ref value);

            switch (value.Type)
            {
            case CorElementType.ELEMENT_TYPE_BOOLEAN:
            case CorElementType.ELEMENT_TYPE_I1:
            case CorElementType.ELEMENT_TYPE_U1:
            case CorElementType.ELEMENT_TYPE_I2:
            case CorElementType.ELEMENT_TYPE_U2:
            case CorElementType.ELEMENT_TYPE_I4:
            case CorElementType.ELEMENT_TYPE_U4:
            case CorElementType.ELEMENT_TYPE_I:
            case CorElementType.ELEMENT_TYPE_U:
            case CorElementType.ELEMENT_TYPE_I8:
            case CorElementType.ELEMENT_TYPE_U8:
            case CorElementType.ELEMENT_TYPE_R4:
            case CorElementType.ELEMENT_TYPE_R8:
            case CorElementType.ELEMENT_TYPE_CHAR:
            {
                object v = value.CastToGenericValue().GetValue();
                string result;

                var vFormattable = v as IFormattable;
                if (vFormattable != null)
                {
                    result = vFormattable.ToString(null, CultureInfo.CurrentUICulture);
                }
                else
                {
                    result = v.ToString();
                }

                // let's put quotes around char values
                if (value.Type == CorElementType.ELEMENT_TYPE_CHAR)
                {
                    result = "'" + result + "'";
                }

                return(prefix + result);
            }

            case CorElementType.ELEMENT_TYPE_CLASS:
            case CorElementType.ELEMENT_TYPE_VALUETYPE:
                CorDebug.CorObjectValue ov = value.CastToObjectValue();
                return(prefix + PrintObject(indentLevel, ov, expandDepth, canDoFunceval));

            case CorElementType.ELEMENT_TYPE_STRING:
                CorDebug.CorStringValue sv = value.CastToStringValue();
                return(prefix + '"' + sv.String + '"');

            case CorElementType.ELEMENT_TYPE_SZARRAY:
            case CorElementType.ELEMENT_TYPE_ARRAY:
                CorDebug.CorArrayValue av = value.CastToArrayValue();
                return(prefix + PrintArray(indentLevel, av, expandDepth, canDoFunceval));

            case CorElementType.ELEMENT_TYPE_PTR:
                return(prefix + "<non-null pointer>");

            case CorElementType.ELEMENT_TYPE_BYREF:
            case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
            case CorElementType.ELEMENT_TYPE_OBJECT:
            default:
                return(prefix + "<printing value of type: " + value.Type + " not implemented>");
            }
        }