int []は参照型ですか、値型ですか?


124

intが値型であることは知っていますが、値型の配列とは何ですか?参照タイプ?値のタイプ?何かをチェックするために、配列を関数に渡したいです。配列の参照を渡すだけなので、配列を渡すだけですか、それともrefとして渡す必要がありますか?


11
将来的には、変数が作成され、その変数を変更するメソッドにその変数を渡し、メソッドを実行した後でその変数の値が何であるかを確認することで、参照または値によって何かが渡されるかどうかを確認できます。同じ場合は、値で渡され、異なる場合は、参照で渡されます。

11
@ darkassassin93:参照渡しまたは値渡しは、何かが参照型であるか値型であるかとは無関係です。(値の型は参照によって渡すことができ、参照の型は値によって渡すことができます。)
LukeH '10 / 07/10

2
ほとんどの場合、フィールドまたは変数内に[null]を格納できる場合は、それがref型であると想定できます。例外は確かにnull文字列(Nullable <int>またはint?)と文字列です。
Noel Widmer

3
@NoëlWidmer文字列も例外ではありません。それらは参照型です。
Arthur Castro 2016年

2
@ArthurCastroが50%に同意:文字列はクラスから継承します。つまり、文字列は参照型です。ただし、それらの等価性は参照ではなくID(値の比較)に基づいており、パスの動作は値の型の動作と一致するようにオーバーライドされます。基本的にそれらは定義では参照型ですが、実装では値型のように動作します。
Noel Widmer 2016年

回答:


201

配列は、複数のアイテムを単一のコレクションとして扱うことができるメカニズムです。Microsoft®.NET共通言語ランタイム(CLR)は、1次元配列、多次元配列、およびギザギザの配列(配列の配列)をサポートしています。すべての配列型は、暗黙的にSystem.Arrayから派生します。それ自体はSystem.Objectから派生します。つまり、 すべての配列は常に マネージヒープに割り当てられる参照型であり、アプリの変数には配列自体ではなく配列への参照が含まれます。

https://msdn.microsoft.com/en-us/library/bb985948.aspx


54
値の型は、System.Objectから継承するSystem.ValueTypeから継承します。つまり、ArrayがSystem.Objectから派生しているからといって、それが参照型であることを意味するわけではありません。System.Arrayを参照型にするのは、インスタンスが参照によってコピーされることです。IOW、System.Arrayがクラスであるという事実に集中してください。それが参照型になります。
P.Brian.Mackey 2013

8
<nitpick>私は、ドキュメントがSystem.Objectから派生したSystem.Arrayが参照型にすることを示唆しているように見える可能性があることを知っています。System.Objectから派生する型が参照型であるとは限りませんが、このルールの唯一の例外はSystem.ValueTypeであり、コンパイラーによって別の方法で処理されます。</ nitpick>
Yannick Motton

上記のリンクは壊れています。ここでのSystem.Arrayの継承階層を示し、他のMSDNのリンクは次のとおりです。msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N

System.Objectから派生するものはすべて参照型であり、System.ValueTypeからも派生する場合を除きます。@ P.Brian.Mackey型がクラスであるという理由だけで、それが参照型であることを意味するわけではありません。背後では、構造体はSystem.ValueTypeから派生した単なるクラスだからです。
David Klempfner 2017年

31

参照型と値型の最も簡単なテストは、参照型がであってもnull、値型がそうでないことです。


46
... null可能であるnull値型を除く(値をnullに設定できます。これは、null 参照ではなく、型のnull値を意味します)、それでも値型です。
Jon Skeet、

1
それらが値型であるかどうかを理解しようとするときにそれをすることを考えたことはありません!いい案。
食欲をそそるエリジウム2009年


6

まず、Arrayが参照型であることをお伝えします。どうして?ここで一例を説明します。

例:

int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.

また、参照型はnullにすることができますが、値型はできません。

スタックに格納されている値の型とヒープに格納されている参照の型

outまたはrefを使用して、配列を関数に渡すことができます。初期化メソッドのみが異なります。

もっと..


3

それが参照型または値型であるかどうかをテストして確認します。

// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************

オンラインでテストできます:https : //dotnetfiddle.net/UWFP45


2
配列を作成してそれをnullに割り当てようとした方が簡単だったでしょう。それは値型..だった場合、コンパイルは失敗するだろう
とりこエリュシオン

あらかじめご了承ください。C#8がリリースされると、null可能ではない参照型もnullを受け入れることができないため、null可能参照型機能を使用している場合も失敗します。
Mark A. Donohoe

2

配列自体は参照型です。その配列の値は、配列のデータ型によって決定される値または参照型です。あなたの例では、配列は参照型であり、値は値型です。

すべての1次元配列は暗黙的にを実装しますIList<T>。ここ<T>で、は配列のデータ型です。代わりに、そのインターフェースをメソッドパラメーターのデータ型として使用できます。IEnumerable<T>データ型にも使用できます。どちらの場合でも(または単にを使用した場合でもint[])、明示的にrefパラメーターとして渡す必要はありません。


0

//配列への参照は値で渡されます。これが混乱の原因です:-) ...

        int[] test = { 1, 2, 3, 4 };

        modifContenuSansRef(test);
        Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié

        modifTailleSansRef(test);
        Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée

    }

    static void modifContenuSansRef(int[] t)
    {
        t[0] = 99;
    }

    static void modifTailleSansRef(int[] t)
    {
        Array.Resize(ref t, 8);
    }

0

配列は常に参照型です。配列にintのような値型またはstringのような参照型が含まれることは問題ではありません。たとえば、配列を宣言する場合

int[] integers=new int[10];

integers変数自体には、ヒープに常駐する配列への参照のみが含まれます。

また、変数がnullであるかどうかという事実に依存するだけで、参照型と値の型が異なる可能性があると多くの人が言及しています。私はc#では現在値型もnullにすることができることを述べたいと思います

例えば

int? integer=null

また、タイプが参照であるか、値が変数がnullであるかどうかというファクトにのみ依存していることを識別するのは良い方法ではありません。


-2

洞察のほんの少し:

たとえば、intは単一の整数をint[]表し、整数の配列を表します。

特定の次元で配列を初期化するには、newキーワードを使用して、型名の後に角括弧でサイズを指定します。

//create a new array of 32 ints.
int[] integers = new int[32];

すべての配列は参照型であり、参照セマンティクスに従います。したがって、このコードでは、個々の要素がプリミティブ値型であるにもかかわらず、integers配列は参照型です。後で書く場合:

int[] copy = integers;

これにより、変数のコピー全体が同じ配列を参照するように割り当てられます。新しい配列は作成されません。

C#の配列構文は柔軟で、初期化せずに配列を宣言できるため、プログラムの後半で配列のサイズを動的に変更できます。この手法では、基本的にnull参照を作成し、後でその参照を、newキーワードで要求された動的に割り当てられたメモリロケーションに向けます。

int[] integers;
integers = new int[32];

ありがとうございました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.