When talking about arrays, when asked what number the array starts from, it is estimated that most programmers will directly say that the array certainly starts from 0. This answer is of course correct. Now let’s take a look at arrays with a non-zero lower limit in C#.
First, let’s take a look at the relevant introduction to arrays:
1. Array: It is a mechanism that allows multiple data items to be processed as a set.
2. Classification of arrays: In CLR, arrays can be divided into one-dimensional arrays, multi-dimensional arrays, and interleaved arrays.
3. Type of array: Since all arrays inherit from the abstract type System.Array, and this type inherits from System.Object, this means that arrays are reference types.
When creating an array, in addition to the array elements, the memory block occupied by the array object also contains a type object pointer, a synchronized index block and an additional member. The above classification of arrays mentioned "interleaved arrays". Since the CLR supports interleaved arrays, interleaved arrays can be implemented in C#. An interleaved array is an array composed of arrays. Accessing the elements of an interleaved array means that it must be done twice. Or multiple array accesses.
In the process of performing related operations on the array, when the array is passed to a method as an actual parameter, what is actually passed is a reference to the array, so the called method can modify the elements in the array. (If you do not want to be modified, you must generate a copy of the array and pass this copy to the method.)
Here is a method to convert an array into a DataTable:
/// <summary> /// 整数型二维数组转换成DataTable /// </summary> /// <param name="intDyadicArray"></param> /// <param name="messageOut"></param> /// <param name="dataTableColumnsName"></param> /// <returns></returns> public DataTable DyadicArrayToDataTable(int[,] intDyadicArray, out string messageOut, params object[] dataTableColumnsName) { var returnDataTable = new DataTable(); //验证列与所传入的字符是否相符 if (dataTableColumnsName.Length != intDyadicArray.GetLength(1)) { messageOut = "DataTable列数与二维数组列数不符,请调整列数"; return returnDataTable; } //添加列 for (var dataTableColumnsCount = 0; dataTableColumnsCount < dataTableColumnsName.Length; dataTableColumnsCount++) { returnDataTable.Columns.Add(dataTableColumnsName[dataTableColumnsCount].ToString()); } //添加行 for (var dyadicArrayRow = 0; dyadicArrayRow < intDyadicArray.GetLength(0); dyadicArrayRow++) { var addDataRow = returnDataTable.NewRow(); for (var dyadicArrayColumns = 0; dyadicArrayColumns < intDyadicArray.GetLength(1); dyadicArrayColumns++) { addDataRow[dataTableColumnsName[dyadicArrayColumns].ToString()] = intDyadicArray[dyadicArrayRow, dyadicArrayColumns]; } returnDataTable.Rows.Add(addDataRow); } //返回提示与DataTable messageOut = "DataTable成功转换"; return returnDataTable; }
The above is the operation method for converting an integer array into a DataTable , as for the conversion of other types, such as bytes, floating point and other types, just modify the relevant parameters, and you can also modify the parameter types accordingly, which will not be introduced in detail here.
Next we will learn more about the "lower limit non-zero array" in detail:
Since the lower limit non-zero array has not been better optimized in terms of performance, it will be less common in general use. If you don't care about performance If there is a loss or need for cross-language portability, consider using a non-zero array. The concept of "lower bound non-zero array" will not be introduced, as its name suggests.
Use Array’s CreateInstance() method to create in C#. This method has several overloads, allowing you to specify the array element type, array dimension, the lower limit of each dimension and the number of elements in each dimension.
When calling CreateInstance(), allocate memory for the array, save the parameter information to the overhead portion of the array's memory, and then return a reference to the array.
Next, let’s take a look at the underlying implementation code of this method:
[System.Security.SecuritySafeCritical] // auto-generated public unsafe static Array CreateInstance(Type elementType, int length) { if ((object)elementType == null) throw new ArgumentNullException("elementType"); if (length < 0) throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); Contract.Ensures(Contract.Result<Array>() != null); Contract.Ensures(Contract.Result<Array>().Length == length); Contract.Ensures(Contract.Result<Array>().Rank == 1); Contract.EndContractBlock(); RuntimeType t = elementType.UnderlyingSystemType as RuntimeType; if (t == null) throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"elementType"); return InternalCreate((void*)t.TypeHandle.Value,1,&length,null); }
After seeing the above code, you should have a general understanding of the creation of non-zero base arrays. Next, let’s take a detailed look at the underlying code of the Ensures() method:
public static void Ensures(bool condition) { AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures"); }
[SecuritySafeCritical] static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind) { if (_assertingMustUseRewriter) System.Diagnostics.Assert.Fail("Asserting that we must use the rewriter went reentrant.", "Didn't rewrite this mscorlib?"); _assertingMustUseRewriter = true; Assembly thisAssembly = typeof(Contract).Assembly; StackTrace stack = new StackTrace(); Assembly probablyNotRewritten = null; for (int i = 0; i < stack.FrameCount; i++) { Assembly caller = stack.GetFrame(i).GetMethod().DeclaringType.Assembly; if (caller != thisAssembly) { probablyNotRewritten = caller; break; } } if (probablyNotRewritten == null) probablyNotRewritten = thisAssembly; String simpleName = probablyNotRewritten.GetName().Name; System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, Environment.GetResourceString("MustUseCCRewrite", contractKind, simpleName), null, null, null); _assertingMustUseRewriter = false; }
The method of creating a non-zero base array will not be introduced in depth. If you need to use it, you can select the corresponding version implementation based on the provided method overload.