詳しくいうと、
string str = "My name is";
str += "Yukiwiro.\n";
とすると、
1.まずメモリ上に My name is というバッファが取られる。
strはそのアドレスを示すリファレンスになる。
2.+=演算子によってメモリ上に My name is Yukiwiro.\n
というバッファが取られる。
str はこのアドレスを示すようになる。
3.ここで、最初の My name is と My name is Yukiwir.\n
は、まったく別もの。
となります。
文字列を結合したりするとそのたびにデータが作成され、str はそのたびに新しく作成されたデータを示すようになります。
ただし、どんどん作成されても、ガーベジコレクションによって開放されるので、気にせず操作することが可能です。
C# において、これを行うには参照というものを使います。
実際に書いてみると、
// C# のコード
int a = 0;
GetData(ref a);
void GetData(ref int a)
{
a = 10;
}
となります。関数の宣言では(ref 型 変数名)とし、呼び出す側では(ref 変数名)とします。
ところで、C/C++のプログラムを書いているとき、こんな経験をしたことがないでしょうか?
int a;
// ここで何か処理するつもりだった。
// しかし実際は、変数 a は使われていない
printf("%d\n", a);
このコードを実行すると、思いもよらない数値が出力されます。
これは変数 a が初期化されなかったため、ごみが表示されてしまったわけです。
C# ではこのようなミスを避けるため必ず変数は初期化しないと使えないという決まりがあります。
そのため、上のコードでは int a = 0; と初期化することで、GetData関数に渡すことができますが、初期化しなければエラーが発生します。
しかしGetDataのようなデータ取得用の場合、初期化せずに渡して関数内で初期化するのがきれいなコードになります。
(意味わからんな・・・。。)
まあ要するに、初期化しなくても使える参照渡しの方法があります。
int a;// 初期化していない
GetData(out a);
void GetData(out int a)
{
a = 10;
}
こうすると、エラーは吐きません。
(outは出力用という意味かな?)
ただし、outがつけられた引数は、必ず関数内で初期化されなければなりません。
void GetData(out int a)
{
return ;// 何もしない
}
とすると、エラーが発生します。
class Fraction
{
}
は、{ 〜 } までが Fraction クラスであると定義します。
クラスの先頭にある
private int denominator;// 分母
private int numerator;// 分子
です。
コメントにもあるように、これらは分母と分子のデータです。
両方int型で宣言され、privateアクセス指定子が付いています。
privateのアクセスレベルは、このクラス以外からはアクセスできないと言う意味です。
なので、object.denominator = 10; なんてことはできません。
次は
public Fraction(int n, int d)
です。
これは、コンストラクタといわれるものです。
コンストラクタとは、クラスが動的静的に関わらず生成された時点で実行されるメンバです。
コンストラクタは戻り値を指定しないクラス名と同じ関数として定義されます。
また、引数を指定して、インスタンスが生成されたら分母と分子を設定するようにしています。
(分母が 0 になることは想定しません。めんどいので…)
struct TestTExplicit
{
union {
long lg;
struct {
int i1;
int i2;
}
}
double d;
char c;
byte b;
};
-------------
C#
[System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]
struct TestExplicit
{
[System.Runtime.InteropServices.FieldOffset(0)]
public long lg;
[System.Runtime.InteropServices.FieldOffset(0)]
public int i1;
[System.Runtime.InteropServices.FieldOffset(4)]
public int i2;
[System.Runtime.InteropServices.FieldOffset(8)]
public double d;
[System.Runtime.InteropServices.FieldOffset(12)]
public char c;
[System.Runtime.InteropServices.FieldOffset(14)]
public byte b;
}