How can I create an ArrayList with a starting index of 1 (instead of 0)

后端 未结 8 636
春和景丽
春和景丽 2021-01-04 09:47

How can I start the index in an ArrayList at 1 instead of 0? Is there a way to do that directly in code?

(Note that I am asking for ArrayList

相关标签:
8条回答
  • 2021-01-04 10:09

    The obvious way to do it would be to wrap an ArrayList in your own implementation, and subtract 1 from the indexer in all operations that uses the index.

    You can in fact also declare an array in .NET, that has an arbitrary lower bound (Scroll down to the section "Creating Arrays with a Non-zero Lower Bound").

    With that said, please don't do it in production code. It matters to be consistent.

    0 讨论(0)
  • 2021-01-04 10:10

    I don't know if it still does, but at one point, Visual Basic would let you start your array indexes at 1 with Option Base 1.

    In C#, none of the System.Collections collections support this, but you could always write a wrapper class that does the index translation for you.

    Really, though, this should be avoided. VB's Option Base created more problems than it solved, I imagine because it broke assumptions and made things more confusing.

    0 讨论(0)
  • 2021-01-04 10:12

    Here is something I am using right now to quickly port a VBA application to C#:

    It's an Array class that starts with 1 and accepts multiple dimensions.

    Although there is some additional work to do (IEnumerator, etc...), it's a start, and is enough to me as I only use indexers.

    public class OneBasedArray<T>
    {
        Array innerArray;
    
        public OneBasedArray(params int[] lengths)
        {
            innerArray = Array.CreateInstance(typeof(T), lengths, Enumerable.Repeat<int>(1, lengths.Length).ToArray());
        }
    
        public T this[params int[] i]
        {
            get
            {
                return (T)innerArray.GetValue(i);
            }
            set
            {
                innerArray.SetValue(value, i);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-04 10:14

    First, let me preface this answer by explaining my use case: Excel Interop. It's much easier to read and write data using arrays, but Excel Range.Value2 magically returns a 1 based object array.

    So, if you are writing to Excel and that's the reason you are asking this question in the first place... then perhaps stop fighting c# and let Excel instantiate the array for you. So instead of:

    object[,] newArray = new object[indexR, indexC];
    

    You can use:

    object[,] newArray = (object[,])RangeToWriteTo.Value2;
    

    In my case, I created a wrapper class to allow me to use an array for the properties like so:

    public abstract class ExcelRowBase
        {
            public object[,] data;
    
            public ExcelRowBase(int index)
            {
                data = new object[2, index + 1];
            }
        }
    
     public class InstanceRowModel : ExcelRowBase 
        {
            public InstanceRowModel() : base(8) 
            { 
            //constructor unique to Wire Table 
            }
    
            public object Configuration
            {
                get
                {
                    return data[1, 1];
                }
                set
                {
                    data[1, 1] = value;
                }
            }
    ...
    

    So in all cases, I'm reading from the same index. So to make the transition from a model I'm passing into a Create method, I just need to copy over the properties into the model that uses the array created from Excel.

                insertingModel.data = (object[,])writeRange.Value2;
    
                //manually copying values from one array to the other
                insertingModel.Configuration = model.Configuration;
                ...
    
                writeRange.Value2 = insertingModel.data;
    

    This works for me for now because I only have to do this in the create function. In update / get / delete, you're getting the Excel based array anyway. Perhaps a future improvement would be to create an Excel range factory that avoids the 0 based default construction all together, but this solution just gave me greens on my tests, so I'm moving on!

    0 讨论(0)
  • 2021-01-04 10:16

    Well, you could make your own:

    public class MyArrayList<T> extends ArrayList<T> {
        public T get(int index) {
            super.get(index - 1);
        }
    
        public void set(int index, T value) {
            super.set(index - 1, value);
        }
    }
    

    But it begs the question: why on earth would you bother?

    0 讨论(0)
  • 2021-01-04 10:27

    As the other answers suggest, there are ways to simulate this, but no direct way to do this in C# or other commonly used .NET languages. Quoting Eric Gunnerson:

    The CLR does support this kind of construct (I had a hard time not using the term "travesty" here...), but there aren't, to my knowledge, any languages that have built-in syntax to do that.

    0 讨论(0)
提交回复
热议问题