ホームページ  >  記事  >  バックエンド開発  >  C# でのゼロ以外の下限による配列解析

C# でのゼロ以外の下限による配列解析

高洛峰
高洛峰オリジナル
2016-11-08 10:10:412061ブラウズ

配列について話すとき、配列が何番から始まるかを尋ねられると、ほとんどのプログラマーは、配列は確かに 0 から始まると直接答えると推定されます。この答えはもちろん正しいです。次に、C# でゼロ以外の下限を持つ配列を見てみましょう。

まず、配列の関連する概要を見てみましょう:

1. 配列: 複数のデータ項目をコレクションとして処理できるようにするメカニズムです。

2. 配列の分類: CLR では、配列は 1 次元配列、多次元配列、インターリーブ配列に分類できます。

3. 配列の型: すべての配列は抽象型 System.Array を継承し、この型は System.Object を継承するため、配列は参照型であることを意味します。

配列を作成する場合、配列要素に加えて、配列オブジェクトによって占有されるメモリ ブロックには、型オブジェクト ポインター、同期インデックス ブロック、および追加のメンバーも含まれます。上記の配列の分類では「インターリーブ配列」について説明しました。CLR はインターリーブ配列をサポートしているため、インターリーブ配列は配列で構成される配列です。インターリーブ配列の要素にアクセスするには、2 回アクセスする必要があります。または複数の配列アクセス。

配列に対して関連する操作を実行するプロセスで、配列が実パラメータとしてメソッドに渡されるとき、実際に渡されるのは配列への参照であるため、呼び出されたメソッドは配列内の要素を変更できます。 (変更されたくない場合は、配列のコピーを生成し、そのコピーをメソッドに渡す必要があります。)

配列を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 に変換する場合、バイト、浮動小数点、その他の型などの他の型の変換と同様に、関連するパラメーターを変更するだけでよく、詳細は紹介しませんが、それに応じてパラメーターの型を変更することもできます。ここ。

次に、「下限非ゼロ配列」について詳しく説明します。

下限非ゼロ配列はパフォーマンスの点で最適化されていないため、一般的に使用されることは少なくなります。パフォーマンスは気にしません。言語間の移植性が失われたり、必要がある場合は、ゼロ以外の配列の使用を検討してください。その名前が示すように、「下限非ゼロ配列」の概念は導入されません。

Array の CreateInstance() メソッドを使用して C# で作成します。このメソッドにはいくつかのオーバーロードがあり、配列要素の型、配列の次元、各次元の下限、および各次元の要素の数を指定できます。

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"); 
        }
[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&#39;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;
        }

ゼロ以外の基本配列を作成するメソッドについては詳しく説明しません。使用する必要がある場合は、提供されたメソッドのオーバーロードに基づいて、対応するバージョンの実装を選択できます。 。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。