protected override bool EmitInternal(TryExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            var il = context.Il;

            il.BeginExceptionBlock();
            returnDefaultValueLabel = context.CanReturn ? il.DefineLabel("returnDefaultValue") : null;
            bool returnDefaultValueLabelUsed = ExpressionEmittersCollection.Emit(node.Body, context, returnDefaultValueLabel, whatReturn, extend, out resultType);

            EmittingContext.LocalHolder retValue = null;
            var doneLabel = il.DefineLabel("done");

            if (resultType == typeof(void))
            {
                if (returnDefaultValueLabelUsed)
                {
                    context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel);
                }
                il.Leave(doneLabel);
            }
            else
            {
                retValue = context.DeclareLocal(resultType);
                il.Stloc(retValue);
                il.Leave(doneLabel);
                if (returnDefaultValueLabelUsed)
                {
                    context.MarkLabelAndSurroundWithSP(returnDefaultValueLabel);
                    if (resultType.IsValueType)
                    {
                        il.Ldloca(retValue);
                        il.Initobj(resultType);
                    }
                    else
                    {
                        il.Ldnull();
                        il.Stloc(retValue);
                    }
                    il.Leave(doneLabel);
                }
            }
            foreach (var catchBlock in node.Handlers)
            {
                bool disposeVariable = false;
                var  variable        = catchBlock.Variable;
                if (catchBlock.Filter == null)
                {
                    il.BeginCatchBlock(catchBlock.Test);
                    if (variable == null)
                    {
                        il.Pop();
                    }
                    else
                    {
                        // todo вызвать ф-цию из AssignExpressionEmitter
                        var index = Array.IndexOf(context.Parameters, variable);
                        if (index >= 0)
                        {
                            il.Starg(index);
                        }
                        else
                        {
                            GroboIL.Local local;
                            if (!context.VariablesToLocals.TryGetValue(variable, out local))
                            {
                                local = context.DeclareLocal(variable.Type);
                                context.VariablesToLocals.Add(variable, local);
                                context.Variables.Push(variable);
                                disposeVariable = true;
                            }
                            il.Stloc(local);
                        }
                    }
                }
                else
                {
                    il.BeginExceptFilterBlock();
                    il.Isinst(catchBlock.Test);
                    il.Dup();
                    var rightTypeLabel = il.DefineLabel("rightType");
                    il.Brtrue(rightTypeLabel);
                    il.Pop();
                    il.Ldc_I4(0);
                    var endFilterLabel = il.DefineLabel("endFilter");
                    il.Br(endFilterLabel);
                    context.MarkLabelAndSurroundWithSP(rightTypeLabel);
                    if (variable == null)
                    {
                        il.Pop();
                    }
                    else
                    {
                        // todo вызвать ф-цию из AssignExpressionEmitter
                        var index = Array.IndexOf(context.Parameters, variable);
                        if (index >= 0)
                        {
                            il.Starg(index);
                        }
                        else
                        {
                            GroboIL.Local local;
                            if (!context.VariablesToLocals.TryGetValue(variable, out local))
                            {
                                local = string.IsNullOrEmpty(variable.Name)
                                                ? context.Il.DeclareLocal(variable.Type)
                                                : context.Il.DeclareLocal(variable.Type, variable.Name, appendUniquePrefix: false);
                                if (context.DebugInfoGenerator != null)
                                {
                                    local.SetLocalSymInfo(local.Name);
                                }
                                context.VariablesToLocals.Add(variable, local);
                                context.Variables.Push(variable);
                                disposeVariable = true;
                            }
                            il.Stloc(local);
                        }
                    }
                    GroboIL.Label returnFalseLabel = context.CanReturn ? il.DefineLabel("returnFalse") : null;
                    Type          filterResultType;
                    bool          returnFalseLabelUsed = ExpressionEmittersCollection.Emit(catchBlock.Filter, context, returnFalseLabel, out filterResultType);
                    if (returnFalseLabelUsed)
                    {
                        il.Br(endFilterLabel);
                        context.MarkLabelAndSurroundWithSP(returnFalseLabel);
                        il.Pop();
                        il.Ldc_I4(0);
                    }
                    context.MarkLabelAndSurroundWithSP(endFilterLabel);
                    il.BeginCatchBlock(null);
                    il.Pop();
                }

                context.EmitLoadArguments(catchBlock.Body);
                if (catchBlock.Body.Type != typeof(void))
                {
                    il.Stloc(retValue);
                }

                if (disposeVariable)
                {
                    context.VariablesToLocals.Remove(variable);
                    context.Variables.Pop();
                }
            }

            if (node.Fault != null)
            {
                il.BeginFaultBlock();
                EmitExpressionAsVoid(node.Fault, context);
            }

            if (node.Finally != null)
            {
                il.BeginFinallyBlock();
                EmitExpressionAsVoid(node.Finally, context);
            }

            il.EndExceptionBlock();

            context.MarkLabelAndSurroundWithSP(doneLabel);
            if (retValue != null)
            {
                il.Ldloc(retValue);
                retValue.Dispose();
            }
            return(false);
        }
        private static void EmitAssign(AssigneeKind assigneeKind, Expression node, EmittingContext context, object[] arguments, EmittingContext.LocalHolder value)
        {
            var il = context.Il;

            switch (assigneeKind)
            {
            case AssigneeKind.Parameter:
                il.Ldloc(value);
                var index = Array.IndexOf(context.Parameters, node);
                if (index >= 0)
                {
                    il.Starg(index);
                }
                else
                {
                    GroboIL.Local variable;
                    if (context.VariablesToLocals.TryGetValue((ParameterExpression)node, out variable))
                    {
                        il.Stloc(variable);
                    }
                    else
                    {
                        throw new InvalidOperationException("Unknown parameter " + node);
                    }
                }
                break;

            case AssigneeKind.SimpleArray:
                il.Ldloc(value);
                il.Stind(node.Type);
                break;

            case AssigneeKind.InstanceField:
            case AssigneeKind.StaticField:
                il.Ldloc(value);
                il.Stfld((FieldInfo)((MemberExpression)node).Member);
                break;

            case AssigneeKind.InstanceProperty:
            case AssigneeKind.StaticProperty:
                il.Ldloc(value);
                var memberExpression = (MemberExpression)node;
                il.Call(((PropertyInfo)memberExpression.Member).GetSetMethod(context.SkipVisibility), memberExpression.Expression == null ? null : memberExpression.Expression.Type);
                break;

            case AssigneeKind.IndexedProperty:
            {
                var indexExpression = (IndexExpression)node;
                if (arguments == null)
                {
                    context.EmitLoadArguments(indexExpression.Arguments.ToArray());
                }
                else
                {
                    foreach (var argument in arguments)
                    {
                        if (argument is Expression)
                        {
                            context.EmitLoadArguments((Expression)argument);
                        }
                        else
                        {
                            var local = (EmittingContext.LocalHolder)argument;
                            il.Ldloc(local);
                            local.Dispose();
                        }
                    }
                }
                il.Ldloc(value);
                MethodInfo setter = indexExpression.Indexer.GetSetMethod(context.SkipVisibility);
                if (setter == null)
                {
                    throw new MissingMethodException(indexExpression.Indexer.ReflectedType.ToString(), "set_" + indexExpression.Indexer.Name);
                }
                context.Il.Call(setter, indexExpression.Object.Type);
            }
            break;

            case AssigneeKind.MultiDimensionalArray:
            {
                var  indexExpression = (IndexExpression)node;
                Type arrayType       = indexExpression.Object.Type;
                if (!arrayType.IsArray)
                {
                    throw new InvalidOperationException("An array expected");
                }
                int rank = arrayType.GetArrayRank();
                if (rank != indexExpression.Arguments.Count)
                {
                    throw new InvalidOperationException("Incorrect number of indeces '" + indexExpression.Arguments.Count + "' provided to access an array with rank '" + rank + "'");
                }
                Type indexType = indexExpression.Arguments.First().Type;
                if (indexType != typeof(int))
                {
                    throw new InvalidOperationException("Indexing array with an index of type '" + indexType + "' is not allowed");
                }
                if (arguments == null)
                {
                    context.EmitLoadArguments(indexExpression.Arguments.ToArray());
                }
                else
                {
                    foreach (var argument in arguments)
                    {
                        if (argument is Expression)
                        {
                            context.EmitLoadArguments((Expression)argument);
                        }
                        else
                        {
                            var local = (EmittingContext.LocalHolder)argument;
                            il.Ldloc(local);
                            local.Dispose();
                        }
                    }
                }
                il.Ldloc(value);
                MethodInfo setMethod = arrayType.GetMethod("Set");
                if (setMethod == null)
                {
                    throw new MissingMethodException(arrayType.ToString(), "Set");
                }
                context.Il.Call(setMethod, arrayType);
            }
            break;
            }
        }
        protected override bool EmitInternal(SwitchExpression node, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            GroboIL il           = context.Il;
            var     defaultLabel = il.DefineLabel("default");
            var     caseLabels   = new GroboIL.Label[node.Cases.Count];

            GroboIL.Label switchValueIsNullLabel = null;
            for (int index = 0; index < node.Cases.Count; index++)
            {
                caseLabels[index] = il.DefineLabel("case#" + index);
            }
            context.EmitLoadArguments(node.SwitchValue);
            using (var switchValue = context.DeclareLocal(node.SwitchValue.Type))
            {
                il.Stloc(switchValue);
                Tuple <int, int, int> switchCase;
                if (context.ParsedLambda.ParsedSwitches.TryGetValue(node, out switchCase))
                {
                    // use simplified hashtable to locate the proper case
                    var labels = new List <GroboIL.Label>();
                    for (int index = 0; index < node.Cases.Count; index++)
                    {
                        foreach (var testValue in node.Cases[index].TestValues)
                        {
                            if (((ConstantExpression)testValue).Value != null)
                            {
                                labels.Add(caseLabels[index]);
                            }
                            else
                            {
                                switchValueIsNullLabel = caseLabels[index];
                            }
                        }
                    }
                    if (switchValueIsNullLabel != null)
                    {
                        if (!node.SwitchValue.Type.IsNullable())
                        {
                            il.Ldloc(switchValue);
                        }
                        else
                        {
                            il.Ldloca(switchValue);
                            context.EmitHasValueAccess(node.SwitchValue.Type);
                        }
                        il.Brfalse(switchValueIsNullLabel);
                    }
                    EmittingContext.LocalHolder pureSwitchValue = switchValue;
                    if (node.SwitchValue.Type.IsNullable())
                    {
                        pureSwitchValue = context.DeclareLocal(node.SwitchValue.Type.GetGenericArguments()[0]);
                        il.Ldloca(switchValue);
                        context.EmitValueAccess(node.SwitchValue.Type);
                        il.Stloc(pureSwitchValue);
                    }
                    Type temp;
                    ExpressionEmittersCollection.Emit(context.ParsedLambda.ConstantsBuilder.MakeAccess(context.ParsedLambda.ConstantsParameter, switchCase.Item1), context, out temp);
                    var type     = node.SwitchValue.Type.IsNullable() ? node.SwitchValue.Type.GetGenericArguments()[0] : node.SwitchValue.Type;
                    var typeCode = Type.GetTypeCode(type);
                    switch (typeCode)
                    {
                    case TypeCode.Byte:
                    case TypeCode.Char:
                    case TypeCode.Int16:
                    case TypeCode.Int32:
                    case TypeCode.Int64:
                    case TypeCode.SByte:
                    case TypeCode.UInt16:
                    case TypeCode.UInt32:
                    case TypeCode.UInt64:
                        il.Ldloc(pureSwitchValue);
                        break;

                    default:
                        if (type.IsValueType)
                        {
                            il.Ldloca(pureSwitchValue);
                        }
                        else
                        {
                            il.Ldloc(pureSwitchValue);
                        }
                        il.Call(typeof(object).GetMethod("GetHashCode"), type);
                        break;
                    }
                    using (var index = context.DeclareLocal(typeof(int)))
                    {
                        if (typeCode == TypeCode.Int64 || typeCode == TypeCode.UInt64)
                        {
                            il.Ldc_I8(switchCase.Item3);
                        }
                        else
                        {
                            il.Ldc_I4(switchCase.Item3);
                        }
                        il.Rem(true);
                        if (typeCode == TypeCode.Int64 || typeCode == TypeCode.UInt64)
                        {
                            il.Conv <int>();
                        }
                        il.Stloc(index);
                        il.Ldloc(index);
                        il.Ldelem(type);
                        il.Ldloc(pureSwitchValue);
                        if (node.Comparison != null)
                        {
                            il.Call(node.Comparison);
                        }
                        else
                        {
                            il.Ceq();
                        }
                        il.Brfalse(defaultLabel);
                        ExpressionEmittersCollection.Emit(context.ParsedLambda.ConstantsBuilder.MakeAccess(context.ParsedLambda.ConstantsParameter, switchCase.Item2), context, out temp);
                        il.Ldloc(index);
                        il.Ldelem(typeof(int));
                        il.Switch(labels.ToArray());
                    }
                    if (pureSwitchValue != switchValue)
                    {
                        pureSwitchValue.Dispose();
                    }
                }
                else
                {
                    // use a number of if/else branches to locate the proper case
                    EmittingContext.LocalHolder pureSwitchValue   = switchValue;
                    EmittingContext.LocalHolder switchValueIsNull = null;
                    if (node.SwitchValue.Type.IsNullable())
                    {
                        pureSwitchValue   = context.DeclareLocal(node.SwitchValue.Type.GetGenericArguments()[0]);
                        switchValueIsNull = context.DeclareLocal(typeof(bool));
                        il.Ldloca(switchValue);
                        il.Dup();
                        context.EmitValueAccess(node.SwitchValue.Type);
                        il.Stloc(pureSwitchValue);
                        context.EmitHasValueAccess(node.SwitchValue.Type);
                        il.Stloc(switchValueIsNull);
                    }
                    for (int index = 0; index < node.Cases.Count; index++)
                    {
                        var caSe  = node.Cases[index];
                        var label = caseLabels[index];
                        foreach (var testValue in caSe.TestValues)
                        {
                            context.EmitLoadArguments(testValue);
                            GroboIL.Label elseLabel = null;
                            if (testValue.Type.IsNullable())
                            {
                                elseLabel = il.DefineLabel("else");
                                using (var temp = context.DeclareLocal(testValue.Type))
                                {
                                    il.Stloc(temp);
                                    il.Ldloca(temp);
                                    context.EmitHasValueAccess(testValue.Type);
                                    if (switchValueIsNull != null)
                                    {
                                        il.Ldloc(switchValueIsNull);
                                        il.Or();
                                        il.Brfalse(label);
                                        il.Ldloca(temp);
                                        context.EmitHasValueAccess(testValue.Type);
                                        il.Ldloc(switchValueIsNull);
                                        il.And();
                                    }
                                    il.Brfalse(elseLabel);
                                    il.Ldloca(temp);
                                    context.EmitValueAccess(testValue.Type);
                                }
                            }
                            il.Ldloc(pureSwitchValue);
                            if (node.Comparison != null)
                            {
                                il.Call(node.Comparison);
                            }
                            else
                            {
                                il.Ceq();
                            }
                            il.Brtrue(label);
                            if (elseLabel != null)
                            {
                                context.MarkLabelAndSurroundWithSP(elseLabel);
                            }
                        }
                    }
                }
            }
            context.MarkLabelAndSurroundWithSP(defaultLabel);
            var doneLabel = il.DefineLabel("done");

            context.EmitLoadArguments(node.DefaultBody);
            il.Br(doneLabel);
            for (int index = 0; index < node.Cases.Count; ++index)
            {
                context.MarkLabelAndSurroundWithSP(caseLabels[index]);
                context.EmitLoadArguments(node.Cases[index].Body);
                if (index < node.Cases.Count - 1)
                {
                    il.Br(doneLabel);
                }
            }
            context.MarkLabelAndSurroundWithSP(doneLabel);
            resultType = node.Type;
            return(false);
        }
        public static bool Emit(Expression zarr, Expression zindex, EmittingContext context, GroboIL.Label returnDefaultValueLabel, ResultType whatReturn, bool extend, out Type resultType)
        {
            var arrayType = zarr.Type;
            var isArray   = arrayType.IsArray;

            if (!isArray && !arrayType.IsList())
            {
                throw new InvalidOperationException("Unable to perform array index operator to type '" + arrayType + "'");
            }
            var     itemType = isArray ? arrayType.GetElementType() : arrayType.GetGenericArguments()[0];
            GroboIL il       = context.Il;

            EmittingContext.LocalHolder arrayIndex = null;
            bool extendArray        = extend && (CanAssign(zarr) || !isArray);
            bool extendArrayElement = extend && itemType.IsClass;
            var  result             = false;

            if (!extendArray)
            {
                result |= ExpressionEmittersCollection.Emit(zarr, context, returnDefaultValueLabel, ResultType.Value, extend, out arrayType); // stack: [array]
                if (context.Options.HasFlag(CompilerOptions.CheckNullReferences))
                {
                    result = true;
                    il.Dup();                              // stack: [array, array]
                    il.Brfalse(returnDefaultValueLabel);   // if(array == null) goto returnDefaultValue; stack: [array]
                }
                EmitLoadIndex(zindex, context, arrayType); // stack: [array, arrayIndex]
                if (context.Options.HasFlag(CompilerOptions.CheckArrayIndexes))
                {
                    result     = true;
                    arrayIndex = context.DeclareLocal(typeof(int));
                    il.Stloc(arrayIndex); // arrayIndex = index; stack: [array]
                    il.Dup();             // stack: [array, array]
                    if (isArray)
                    {
                        il.Ldlen(); // stack: [array, array.Length]
                    }
                    else
                    {
                        EmitLoadField(context, arrayType, arrayType.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic));
                    }
                    il.Ldloc(arrayIndex);                   // stack: [array, array.Length, arrayIndex]
                    il.Ble(returnDefaultValueLabel, false); // if(array.Length <= arrayIndex) goto returnDefaultValue; stack: [array]
                    il.Ldloc(arrayIndex);                   // stack: [array, arrayIndex]
                    il.Ldc_I4(0);                           // stack: [array, arrayIndex, 0]
                    il.Blt(returnDefaultValueLabel, false); // if(arrayIndex < 0) goto returnDefaultValue; stack: [array]
                }
                else if (extendArrayElement || !isArray)
                {
                    arrayIndex = context.DeclareLocal(typeof(int));
                    il.Stloc(arrayIndex); // arrayIndex = index; stack: [array]
                }
            }
            else
            {
                EmittingContext.LocalHolder arrayOwner = null;
                switch (zarr.NodeType)
                {
                case ExpressionType.Parameter:
                case ExpressionType.ArrayIndex:
                case ExpressionType.Index:
                    Type type;
                    ExpressionEmittersCollection.Emit(zarr, context, returnDefaultValueLabel, ResultType.ByRefAll, true, out type); // stack: [ref array]
                    arrayOwner = context.DeclareLocal(type);
                    il.Dup();                                                                                                       // stack: [ref array, ref array]
                    il.Stloc(arrayOwner);                                                                                           // arrayOwner = ref array; stack: [ref array]
                    il.Ldind(zarr.Type);                                                                                            // stack: [array]
                    break;

                case ExpressionType.MemberAccess:
                    var  memberExpression = (MemberExpression)zarr;
                    Type memberType;
                    context.EmitMemberAccess(memberExpression, returnDefaultValueLabel, context.Options.HasFlag(CompilerOptions.CheckNullReferences), true, ResultType.ByRefValueTypesOnly, out memberType, out arrayOwner); // stack: [array]
                    break;

                default:
                    throw new InvalidOperationException("Cannot extend array for expression with node type '" + zarr.NodeType + "'");
                }
                if (context.Options.HasFlag(CompilerOptions.CheckNullReferences))
                {
                    il.Dup();                            // stack: [array, array]
                    il.Brfalse(returnDefaultValueLabel); // if(array == null) goto returnDefaultValue; stack: [array]
                }
                EmitLoadIndex(zindex, context, arrayType);
                result     = true;
                arrayIndex = context.DeclareLocal(typeof(int));
                il.Stloc(arrayIndex);                   // arrayIndex = index; stack: [array]
                il.Ldloc(arrayIndex);                   // stack: [array, arrayIndex]
                il.Ldc_I4(0);                           // stack: [array, arrayIndex, 0]
                il.Blt(returnDefaultValueLabel, false); // if(arrayIndex < 0) goto returnDefaultValue; stack: [array]
                il.Dup();                               // stack: [array, array]
                if (isArray)
                {
                    il.Ldlen(); // stack: [array, array.Length]
                }
                else
                {
                    EmitLoadField(context, arrayType, arrayType.GetField("_size", BindingFlags.Instance | BindingFlags.NonPublic));
                }
                il.Ldloc(arrayIndex);          // stack: [array, array.Length, arrayIndex]
                var bigEnoughLabel = il.DefineLabel("bigEnough");
                il.Bgt(bigEnoughLabel, false); // if(array.Length > arrayIndex) goto bigEnough; stack: [array]
                using (var array = context.DeclareLocal(arrayType))
                {
                    il.Stloc(array); // stack: []
                    if (!isArray)
                    {
                        EnsureCount(context, array, arrayIndex, arrayType);
                    }
                    else
                    {
                        il.Ldloca(array);                                                         // stack: [ref array]
                        il.Ldloc(arrayIndex);                                                     // stack: [ref array, arrayIndex]
                        il.Ldc_I4(1);                                                             // stack: [ref array, arrayIndex, 1]
                        il.Add();                                                                 // stack: [ref array, arrayIndex + 1]
                        il.Call(arrayResizeMethod.MakeGenericMethod(arrayType.GetElementType())); // Array.Resize(ref array, 1 + arrayIndex); stack: []

                        switch (zarr.NodeType)
                        {
                        case ExpressionType.Parameter:
                        case ExpressionType.ArrayIndex:
                        case ExpressionType.Index:
                            il.Ldloc(arrayOwner); // stack: [ref parameter]
                            il.Ldloc(array);      // stack: [ref parameter, array]
                            il.Stind(arrayType);  // parameter = array; stack: []
                            break;

                        case ExpressionType.MemberAccess:
                            var memberExpression = (MemberExpression)zarr;
                            if (memberExpression.Expression != null)
                            {
                                il.Ldloc(arrayOwner);
                            }
                            il.Ldloc(array);
                            switch (memberExpression.Member.MemberType)
                            {
                            case MemberTypes.Field:
                                il.Stfld((FieldInfo)memberExpression.Member);
                                break;

                            case MemberTypes.Property:
                                var propertyInfo = (PropertyInfo)memberExpression.Member;
                                var setter       = propertyInfo.GetSetMethod(context.SkipVisibility);
                                if (setter == null)
                                {
                                    throw new MissingMethodException(propertyInfo.ReflectedType.ToString(), "set_" + propertyInfo.Name);
                                }
                                il.Call(setter, memberExpression.Expression == null ? null : memberExpression.Expression.Type);
                                break;

                            default:
                                throw new NotSupportedException("Member type '" + memberExpression.Member.MemberType + "' is not supported");
                            }
                            break;

                        default:
                            throw new InvalidOperationException("Unable to assign array to an expression with node type '" + zarr.NodeType);
                        }
                    }
                    il.Ldloc(array);
                    context.MarkLabelAndSurroundWithSP(bigEnoughLabel);
                }
            }

            if (!isArray)
            {
                // TODO: это злобно, лист при всех операциях меняет _version, а мы нет
                EmitLoadField(context, arrayType, arrayType.GetField("_items", BindingFlags.Instance | BindingFlags.NonPublic));
                arrayType = itemType.MakeArrayType();
            }

            if (extendArrayElement)
            {
                // stack: [array]
                var constructor = itemType.GetConstructor(Type.EmptyTypes);
                if (itemType.IsArray || constructor != null)
                {
                    using (var array = context.DeclareLocal(arrayType))
                    {
                        il.Dup();             // stack: [array, array]
                        il.Stloc(array);      // stack: [array]
                        il.Ldloc(arrayIndex); // stack: [array, arrayIndex]
                        il.Ldelem(itemType);  // stack: [array[arrayIndex]]
                        var elementIsNotNullLabel = il.DefineLabel("elementIsNotNull");
                        il.Brtrue(elementIsNotNullLabel);
                        il.Ldloc(array);
                        il.Ldloc(arrayIndex);
                        context.Create(itemType);
                        il.Stelem(itemType);
                        context.MarkLabelAndSurroundWithSP(elementIsNotNullLabel);
                        il.Ldloc(array);
                    }
                }
            }
            if (arrayIndex != null)
            {
                il.Ldloc(arrayIndex);
                arrayIndex.Dispose();
            }
            switch (whatReturn)
            {
            case ResultType.ByRefAll:
                il.Ldelema(itemType);
                resultType = itemType.MakeByRefType();
                break;

            case ResultType.ByRefValueTypesOnly:
                if (itemType.IsValueType)
                {
                    il.Ldelema(itemType);
                    resultType = itemType.MakeByRefType();
                }
                else
                {
                    il.Ldelem(itemType); // stack: [array[arrayIndex]]
                    resultType = itemType;
                }
                break;

            default:
                il.Ldelem(itemType); // stack: [array[arrayIndex]]
                resultType = itemType;
                break;
            }
            return(result);
        }