C#値型と参照型学習

ディレクトリ

1.はじめに

2.コンセプト

値のタイプ

参照タイプ

文字列探索

3. Common System Type(CTS)

4.値型と参照型のメモリへの配置

スタックとヒープの理解

積み重ね

ヒープ

スタックとヒープでの値型と参照型の割り当て

5.値のタイプと参照タイプの該当する場合

参考資料


1.はじめに

私はC#をほぼ2年間学習しています。CとC ++は初めてですが、基本を知らないため、C#で勉強するときに基本にあまり時間をかけませんでした。その後、プロジェクトで問題が発生しました。仕事を探すつもりですが、まだ基礎を学ばなければならないようですが、今日はC#の値の型と参照の型の違いを見てみましょう。

2.コンセプト

c#には2つの基本的なタイプがあります、それらは値タイプと参照タイプです

値のタイプ

変数はメモリに直接格納され、バイト、ショート、整数、ロング、フロート、ダブル、デシマル、チャー、ブール、および構造は、まとめて値型と呼ばれます。すべての値の型は暗黙的に封印され(新しい値の型は派生できません)、目的は他の型が値の型から派生するのを防ぐことです。値型変数が宣言されると、コンパイラーは、割り当てられているかどうかに関係なく、その変数にメモリを割り当てます。

C#のすべての値の型は、System.ValueTypeから暗黙的に派生します。

構造:構造体(System.ValueTypeから直接派生);
値のタイプ:

  • 整型:sbyte(System.SByte的别名)、short(System.Int16)、int(System.Int32)、long(System.Int64)、byte(System.Byte)、ushort(System.UInt16)、uint(System .UInt32)、ulong(System.UInt64)、char(System.Char);
  • 浮点型:float(System.Single)、double(System.Double);
  • decimal(System.Decimal)。財務計算で高精度に使用されます。
  • boolタイプ:bool(System.Booleanのエイリアス);
  • 構造体(System.ValueTypeから派生)。
  • 列挙型(System.Enumから派生);
  • Nullable型(System.Nullable <T>ジェネリック構造から派生、T?は実際にはSystem.Nullable <T>のエイリアスです)。

参照型と値型の両方がSystem.Objectクラスから継承されることに注意してください。違いは、ほとんどすべての参照型がSystem.Objectから直接継承するのに対し、値型はサブクラスを継承する、つまりSystem.ValueTypeを直接継承することです。System.ValueTypeは、System.Objectから直接派生しています。つまり、System.ValueType自体はクラス型であり、値型ではありません。重要なのは、ValueTypeがEquals()メソッドを書き換えて、値の型が参照アドレスではなくインスタンスの値に従って比較されることです。

Type.IsValueTypeプロパティを使用して、型が値型かどうかを判断できます。

TestType testType = new TestType ();
if (testTypetype.GetType().IsValueType)
{
     Console.WriteLine("{0} is value type.", testType.ToString());
}

参照タイプ

参照型変数はデータへの参照を保持します。データはデータヒープに格納されます。文字列とクラスはまとめて参照型と呼ばれます。クラスを宣言するとき、アドレスを保持するためにスタックに割り当てられるメモリはごくわずかであり、現時点ではヒープ上のメモリ空間は割り当てられてませんnewを使用してクラスのインスタンスを作成する場合は、ヒープにスペースを割り当て、ヒープ上のスペースのアドレスをスタックに割り当てられた小さなスペースに保存します。

C#には次の参照タイプがあります。

  • 配列(System.Arrayから派生)
  • ユーザーは次のタイプを定義します。
  • クラス:クラス(System.Objectから派生);
  • インターフェース:インターフェース(インターフェースは「何か」ではないので、どこから派生するかは問題ではありません。アンダースは「C#プログラミング言語」で、インターフェースは単なる規則[契約]であると述べています);
  • デリゲート:デリゲート(System.Delegateから派生)。
  • オブジェクト(System.Objectのエイリアス);
  • 文字列:文字列(System.Stringのエイリアス)。

文字列探索

明らかに文字列の割り当てはすべて値型ですが、参照型はどうですか?

.netフレームワークプログラミング(改訂版)の説明は次のとおりです。

文字列型はObjectを直接継承するため、それを参照型にします。これは、スレッドのスタックに文字列が存在しないことを意味します。

名前

CTSタイプ

解説

ストリング

System.String

Unicode文字列

string s1 = "aaaa";
 
string s2 = s1;
 
Console.WriteLine("s1:" + s1);
 
Console.WriteLine("s2:" + s2);
 
s1 = "bbbb";
 
Console.WriteLine("s1:" + s1);
 
Console.WriteLine("s2:" + s2);
 
Console.ReadKey();

文字列文字列では、S1アドレスは最初はaaaaを指し、S2 = S1なので、S2アドレスもaaaaを指します。示されているように

bbbbがS1に再度割り当てられると、データbbbbがヒープ内で開かれ、aaaaデータが消えたり、上書きされたりすることはありません。S1アドレスはヒープ内のbbbbを指します

S2アドレスはまだaaaaを指しています。示されているように

上記のコードは値タイプを割り当てますが、stringは参照タイプです。文字列はスタックではなくヒープに割り当てられます。したがって、文字列変数を別の文字列に割り当てると、メモリ内の同じ文字列への2つの参照が取得されます。ただし、文字列型と参照型には、一般的な操作にいくつかの違いがあります。たとえば、文字列は不変です。文字列の1つを変更すると、新しい文字列オブジェクトが作成されますが、他の文字列は変更されません。

3. Common System Type(CTS)

C#の基本的なデータ型は、プラットフォームに依存しない方法で定義されます。C#の定義済みの型は言語に組み込まれていませんが、.NET Frameworkに組み込まれています。すべての.NET指向の言語は、最終的にILにコンパイルされます。

たとえば、int変数がC#で宣言されている場合、それは実際にはCTSのSystem.Int32のインスタンスです。これには重要な影響があります
。ILでの必須の型安全性の確保
、異なる.NET言語間の相互運用性の実現、
すべてのデータ型はオブジェクトです。メソッド、プロパティなどを持つことができます。例:ToString()。

4.値型と参照型のメモリへの配置

スタックとヒープの理解

積み重ね

スタックは、データの一方の端、つまりスタックの最上部でのみ操作できます。

スタックもメモリの自己管理構造であり、スタックをプッシュすると自動的にメモリが割り当てられ、スタックをポップすると自動的に占有メモリがクリアされます。

  注目に値する他の2つのポイント:

     1. スタック内のメモリを動的に要求することはできず、一定サイズのデータ​​にしか割り当てることができないため、柔軟性は高くありませんが、スタックの実行効率は高くなります。

     2.スタック上の使用可能なスペースは大きくないため、スタックに割り当てられたデータを操作するときは、データのサイズの影響に注意する必要があります。

ヒープ

   ヒープはスタックとは異なります。ヒープは、C#に実際のインスタンスオブジェクトを格納するために使用されます。C#は大量のデータを格納でき、ヒープは動的にストレージスペースを割り当てることができます

   スタックは片端でしか操作できないのと比較して、ヒープ内のデータには自由にアクセスできます

   ただし、ヒープの構造は、ヒープの実行効率をスタックほど高くせず、使用されたオブジェクトを自動的にリサイクルすることはできません。ヒープ内のメモリリカバリの場合、C ++プログラマは手動リカバリを実行する必要があります。これはC ++プログラミングでも注目に値します。そうしないと、メモリオーバーフローが発生しやすくなります。.NETプログラマー向けに、プラットフォームは、ヒープ内の期限切れオブジェクトを自動的に収集できるガベージコレクション(GC)メカニズムを提供します。

スタックとヒープでの値型と参照型の割り当て

ここには2つの原則があります。

    (1)参照型を作成すると、ランタイムはそれに2つのスペースを割り当てます。1つのスペースは参照型自体のデータを格納するためにヒープに割り当てられ、もう1つのブロックスペースはヒープにデータへの参照を格納するためにスタックに割り当てられます(実際には格納されたヒープ上のメモリアドレス、つまりポインタ)。

    (2)値のタイプを作成すると、ランタイムはそのスペースを割り当てます。このスペースは、変数が作成された場所に割り当てられます

      値タイプがメソッド内で作成された場合、メソッドはスタックにプッシュされ、ストレージ用のスタックに割り当てられます。

      値タイプが参照タイプのメンバー変数である場合、それは参照タイプに従い、ヒープに格納されます。

より詳細な導入リファレンス:https : //blog.csdn.net/qiaoquan3/article/details/51202926

5.値のタイプと参照タイプの該当する場合

値型はメモリ管理の効率が高く、データを格納するキャリアとしての使用に適したポリモーフィズムをサポートしていません。参照型は、アプリケーションの動作を定義するのに適したポリモーフィズムをサポートしています。

C#では、構造体/クラスを使用して、型を値型/参照型として宣言します。次の例を考えてみましょう:
SomeType [] oneTypes = new SomeType [100];
SomeTypeが値タイプの場合、割り当てる必要があるのは1回だけで、サイズはSomeTypeのサイズの100倍です。SomeTypeが参照型の場合、最初に100個の割り当てが必要です。割り当て後、配列の各要素の値はnullになり、その後100個の要素が初期化されるため、合計101回の割り当てが必要です。これはより多くの時間を消費し、より多くのメモリの断片化を引き起こします。したがって、タイプの責任が主にデータの格納である場合、値タイプがより適切です。
一般に、値のタイプ(多態性をサポートしていない)は、C#アプリケーション操作のデータの格納に適しています。参照タイプ(多態性をサポート)を使用して、アプリケーションの動作を定義する必要があります。通常、値型よりも多くの参照型を作成します。次の条件が満たされている場合は、値タイプを作成する必要があります
。このタイプの主な役割はデータストレージに使用されます。 
このタイプの共通インターフェースは、一部のデータメンバーアクセス属性によって完全に定義されています。 
この型にサブクラスを含めることはできません。 
このタイプにはポリモーフィックな動作はありません。
 

参考資料

Cの参照型と値型#

Cの値タイプと参照タイプ#

文字列型はCの値型または参照型ですか?

C#値タイプと参照タイプの違いを説明する

元の記事を30件公開 Like1 Visits1158

おすすめ

転載: blog.csdn.net/chunchunlaila/article/details/105472903