/// <returns> /// The qualified name (i.e. including containing types and namespaces) of a named, pointer, /// or array type followed by the qualified name of the actual runtime type, if provided. /// </returns> internal static string GetTypeName( DkmInspectionContext inspectionContext, DkmClrValue value, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, bool isPointerDereference) { var declaredLmrType = declaredType.GetLmrType(); var runtimeType = value.Type; var declaredTypeName = inspectionContext.GetTypeName(declaredType, declaredTypeInfo, Formatter.NoFormatSpecifiers); // Include the runtime type if distinct. if (!declaredLmrType.IsPointer && !isPointerDereference && (!declaredLmrType.IsNullable() || value.EvalFlags.Includes(DkmEvaluationResultFlags.ExceptionThrown))) { // Generate the declared type name without tuple element names. var declaredTypeInfoNoTupleElementNames = declaredTypeInfo.WithNoTupleElementNames(); var declaredTypeNameNoTupleElementNames = (declaredTypeInfo == declaredTypeInfoNoTupleElementNames) ? declaredTypeName : inspectionContext.GetTypeName(declaredType, declaredTypeInfoNoTupleElementNames, Formatter.NoFormatSpecifiers); // Generate the runtime type name with no tuple element names and no dynamic. var runtimeTypeName = inspectionContext.GetTypeName(runtimeType, null, FormatSpecifiers: Formatter.NoFormatSpecifiers); // If the two names are distinct, include both. if (!string.Equals(declaredTypeNameNoTupleElementNames, runtimeTypeName, StringComparison.Ordinal)) // Names will reflect "dynamic", types will not. { return string.Format("{0} {{{1}}}", declaredTypeName, runtimeTypeName); } } return declaredTypeName; }