internal static void SetItem(VariableArrayBase <TItem, TArray> array, TItem itemPrototype, TItem value, params IModelExpression[] index)
        {
            TItem item = GetItem(array, itemPrototype, index);

            //  SetTo already checks for compatible indexing.
            //item.CheckCompatibleIndexing(value);
            item.SetTo(value);
            if (Variable.AutoNaming)
            {
                //this.Name = value.ArrayVar.ToString();// +"," + range.Name;
            }
        }
        /// <summary>
        /// Get a random variable representing an item of an array.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="itemPrototype"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        internal static TItem GetItem(VariableArrayBase <TItem, TArray> array, TItem itemPrototype, params IModelExpression[] index)
        {
            Set <Range>   switchRanges = new Set <Range>();
            IList <Range> ranges       = array.Ranges;

            if (index.Length != ranges.Count)
            {
                throw new ArgumentException("Provided " + index.Length + " indices to an array of rank " + ranges.Count);
            }
            for (int i = 0; i < ranges.Count; i++)
            {
                ranges[i].CheckCompatible(index[i], array);
                foreach (SwitchBlock block in StatementBlock.EnumerateOpenBlocks <SwitchBlock>())
                {
                    if (block.Range.Equals(index[i]))
                    {
                        throw new ArgumentException("Cannot index by '" + index[i] + "' in a switch block over '" + block.ConditionVariable + "'");
                    }
                }
            }
            IVariable item;
            Dictionary <IReadOnlyList <IModelExpression>, IVariable> itemVariables = ((HasItemVariables)array).GetItemsUntyped();

            if (itemVariables.TryGetValue(index, out item))
            {
                return((TItem)item);
            }
            // the item must be in the same containers as the array (not the currently open containers)
            if (itemPrototype is IVariableArray)
            {
                Dictionary <Range, Range> replacements = new Dictionary <Range, Range>();
                Dictionary <IModelExpression, IModelExpression> expressionReplacements = new Dictionary <IModelExpression, IModelExpression>();
                for (int i = 0; i < ranges.Count; i++)
                {
                    expressionReplacements.Add(ranges[i], index[i]);
                }
                IVariable result = ((IVariableArray)itemPrototype).ReplaceRanges(replacements, expressionReplacements, deepCopy: false);
                TItem     v      = (TItem)result;
                v.MakeItem(array, index);
                return(v);
            }
            else
            {
                TItem v = (TItem)itemPrototype.Clone();
                v.MakeItem(array, index);
                return(v);
            }
        }
        /// <summary>
        /// Set the variable array to the given value
        /// </summary>
        /// <param name="that"></param>
        public void SetTo(VariableArrayBase <TItem, TArray> that)
        {
            bool foundDef = false;

            foreach (TItem item in that.items.Values)
            {
                if (item.IsDefined)
                {
                    SetItem(this, itemPrototype, item, item.indices.ToArray());
                    foundDef = true;
                }
            }
            if (!foundDef)
            {
                base.SetTo(that);
            }
        }
 /// <summary>
 /// Copy constructor.
 /// </summary>
 /// <param name="array"></param>
 protected VariableArrayBase(VariableArrayBase <TItem, TArray> array)
     : base(array)
 {
     this.ranges        = array.ranges;
     this.itemPrototype = array.itemPrototype;
 }