zoukankan      html  css  js  c++  java
  • 数组未必一定需从0开始,谈一下非0开始的数组

      谈到数组时,当被问及数组是从什么数开始时,估计大部分程序员都会直接说出数组当然是从0开始的。这个回答当然没有错,现在我们就来了解一下C#中的下限非0的数组。

      首先看一下数组的相关介绍:

          1.数组:是允许将多个数据项当作一个集合来处理的机制。

          2.数组的分类:在CLR中,数组可分为一维数组,多维数组,交错数组。

          3.数组的类型:由于所有的数组都是继承自System.Array这个抽象类型,而这个类型又是继承自System.Object,这就说明数组是引用类型。

      在创建数组时,除了有数组元素,数组对象占据的内存块还包含一个类型对象指针,一个同步索引块和一个额外的成员。上面对数组的分类中提到“交错数组”,由于CLR支持交错数组,所以在C#中可以实现交错数组,交错数组即由数组构成的数组,在访问交错数组的元素意味着必须进行两次或多次数组访问。

      在对数组进行相关操作的过程中,数组作为实参传给一个方法时,实际传递的是对该数组的引用,因此被调用的方法能够修改数组中的元素。(如果不想被修改,必须生成数组的一个拷贝,并将这个拷贝传给方法。)

      下面介绍一种将数组转化为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;
            }

         以上是将整数数组转化为DataTable的操作方法,至于其他类型,如字节,浮点型等类型的转化,修改相关参数即可,也可将参数类型进行对应的修改,这里就不做详细介绍了。

         接下来我们具体来了解一下“下限非零数组”的相关知识:

           下限非零数组由于在性能上没有做更好的优化,因此在一般的使用中会较少,如果不计较性能损失或者需要跨语言移植,可以考虑使用非零数组。“下限非零数组”的概念就不做介绍,正如其名称所见。

          C#中使用Array的CreateInstance()方法进行创建,此方法有若干个重载,允许指定数组元素类型,数组维数,每一维的下限和每一维的元素数目。

          在调用CreateInstance()时,为数组分配内存,将参数信息保存到数组的内存的开销部分,然后返回对数组的一个引用。

          接下来看一下此方法的底层实现代码:

     [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); 
            }

       看到以上的代码,应该对非零基数组的创建有一个大致了解,接下来具体看一下Ensures()方法的底层代码:

    public static void Ensures(bool condition)
            {
                AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures"); 
            }
    static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind); 
            [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;
            } 

         有关非零基数组的创建方法就不做深入的介绍,如果需要使用,可以根据提供的方法重载选择对应的版本实现。

  • 相关阅读:
    py笔记之循环结构
    PY学习记录#5
    PY学习记录#4
    py笔记之选择结构
    PY学习记录#3
    分享一个可以随时随地写代码的工具
    PY学习记录#2
    日记啊
    Tarjan学习笔记
    Docker commands
  • 原文地址:https://www.cnblogs.com/pengze0902/p/6037897.html
Copyright © 2011-2022 走看看