C#では、クラスは参照型、構造体は値型という大きな違いがある・・・。
TestClass.csを、
using System;
class TestClass
{
private string str;
public string Str
{
get
{
return str;
}
set
{
str = value;
}
}
private int i;
public int I
{
get
{
return i;
}
set
{
i = value;
}
}
public void Show()
{
Console.WriteLine("i = " + i + ", str = " + str);
}
}
TestStruct.csを、
using System;
struct TestStruct
{
private string str;
public string Str
{
get
{
return str;
}
set
{
str = value;
}
}
private int i;
public int I
{
get
{
return i;
}
set
{
i = value;
}
}
public void Show()
{
Console.WriteLine("i = " + i + ", str = " + str);
}
}
としておく・・・。
そして、MainClass.csでいろいろ試してみる・・・。
using System;
class MainClass
{
static void Main()
{
TestClass testClass;
TestStruct testStruct;
if (testClass == null)
{
Console.WriteLine("testClass == null!");
}
if (testStruct == null)
{
Console.WriteLine("testStruct == null!");
}
}
}
まず、こうしてみたら、
------ ビルド開始: プロジェクト: struct, 構成: Debug Any CPU ------
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /debug+ /debug:full /optimize- /out:obj\Debug\struct.exe /target:exe MainClass.cs TestClass.cs TestStruct.cs
C:\Project\Cloud\github.com\Sample\cs\struct\struct\src\struct\struct\MainClass.cs(21,13): エラー CS0019: 演算子 '==' を 'TestStruct' と '<null>' 型のオペランドに適用することはできません。
コンパイルの完了 -- エラー 1、警告 0
========== ビルド: 0 正常終了または最新の状態、1 失敗、0 スキップ ==========
と出た・・・。testStructは値型なのでnullとは比較できないようだ・・・。
testStruct関係はいったんコメントアウトして、
TestClass testClass;
TestStruct testStruct;
if (testClass == null)
{
としてみたら、
C:\Project\Cloud\github.com\Sample\cs\struct\struct\src\struct\struct\MainClass.cs(17,13): エラー CS0165: 未割り当てのローカル変数 'testClass' が使用されました。
未割当だとnull比較さえ、ダメみたいだ・・・。
(C++だとこういうのはせいぜい警告で済むのだが厳しい・・・。)
TestClass testClass;
TestStruct testStruct;
testClass = new TestClass();
おとなしくnewでインスタンス生成・・・。
testClass = new TestClass();
testClass.I = 10;
testClass.Str = "A";
testClass.Show();
プロパティもメソッドも呼べる・・・。
さて、構造体だとどうだろうか・・・。
さっきのnull判定はしょうがないとして、
TestClass testClass;
TestStruct testStruct;
testClass = new TestClass();
testStruct.I = 100;
構造体は宣言時にメモリが割り当てられているらしいので、プロパティ経由で値を入れようとしたが、
C:\Project\Cloud\github.com\Sample\cs\struct\struct\src\struct\struct\MainClass.cs(20,9): エラー CS0165: 未割り当てのローカル変数 'testStruct' が使用されました。
割り当てられているなら「newはいらないのでは?」とおもった・・・。
そこで、TestStruct.csで、
や、
というように、privateメンバフィールドをpublicにして、
testStruct.i = 100;
メンバフィールドに直接入れてみる・・・。
これだと、
コンパイルの完了 -- エラー 0、警告 0
通ってしまう・・・。
testStruct.str = "ABC";
これも通る・・・。
しかし、プロパティ経由だと通らない・・・。
そして、
testStruct.Show();
メソッドでも通らなかった・・・。
どうも、アクセスできるのはメンバフィールドだけの模様・・・。
実は構造体にもnewがある・・・。
testStruct = new TestStruct();
コメントにもあるようにこれは、TestStructオブジェクトを生成し、その参照をtestStructに渡しているわけではなく、そのオブジェクトごとtestStructにコピーしているのである・・・。
なので、まあnew TestStructは無駄になるのだが・・・。
しかし、こうすると、
testStruct = new TestStruct();
testStruct.I = 100;
testStruct.Str = "ABC";
testStruct.Show();
これでも、
コンパイルの完了 -- エラー 0、警告 0
通る・・・。
(ふしぎー・・・。)
やはり、構造体はnewで生成してコンストラクタなどで値を初期化すべきだなあ・・・。
さて、クラスは参照型、構造体は値型、ということであれば、クラスオブジェクトは参照渡し、構造体オブジェクトはコピーになることも確認しないと・・・。
最終的にMainClass.csは、
として、ClassStructMethodにtestClassオブジェクトと、testStructオブジェクトを渡して、内部でメンバを変更したらそれが反映されるかを試してみる・・・。
i = 10, str = A
i = 100, str = ABC
i = 20, str = X
i = 100, str = ABC
続行するには何かキーを押してください . . .
最終的な結果はこうなる・・・。
testClassは参照型なので、メンバの値の変更が反映されてる・・・。
一方、testStructはコピーで渡されるので、メンバの値の変更は元のオブジェクトに影響しない・・・。
※.訂正
プロパティとメソッドが呼べない件は、
構造体 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
全てのフィールドの初期化までは呼べない制約で、生成とかの話ではない模様・・・。
Sample/cs/struct/struct/src/struct at master · bg1bgst333/Sample · GitHub