【2025NEWチップス発売12か月の品質保証 】type-c カードリーダー 2in1 カメラリーダー SD カードリーダー TRAOO SD/TFカードリーダー USB 3.0 OTG機能 写真/ビデオ/データ 双方向高速転送 i-Phone 16/i-Pad Pro/MacBook/Chromebook/AndroidスマホなどUSB Cポート搭載機器に対応
¥748 (2025年4月26日 13:09 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)【2025最新型】icカードリーダー マイナンバーカード対応 USB-A&Type-C 接触型 sdカードリーダー 設置不要 自宅で確定申告 国税電子申告 納税システム e-Tax対応マイナンバーカード ICチップ付いた住民基本台帳カード SDカード/マイナンバーカード/キャッシュカード その他対応 Windows11/10/8/7/Vista/macOS 10.16以降 日本語説明書付き
¥1,299 (2025年4月26日 13:05 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
C# では 配列のインデクサが参照戻り値対応しているのでそれでいってみます。
値型(かへn)
例えばこういった構造体(値型)があったとするじゃないですか。
record struct V1(string Value);
C# でいう record struct は可変な 構造体レコードです。
次の様な操作をするとどうなるでしょうか?
V1[] array = [new("1"), new("2"), new("3"), new("4"), new("5")];
Console.WriteLine($"1:before: {ToString(array)}");
int i = 0;
{
// 0: 配列のインデクサは参照戻り値
array[i++].Value = "🐁";
}
{
// 代入(値渡し)
{
var v = array[i++];
//1: プロパティを変更
v.Value = "🐄";
}
{
var v = array[i++];
//2: インスタンスを更新
v = v with {
Value = "🐅",
};
}
}
{
// ref ローカル変数 (参照渡し)
{
ref var v = ref array[i++];
//3: プロパティを変更
v.Value = "🐈";
}
{
ref var v = ref array[i++];
//4: インスタンスを更新
v = v with {
Value = "🐒",
};
}
}
Console.WriteLine($"1:after : {ToString(array)}");
string ToStringT>(T[] array) => string.Join(",", array.Select(v => $"{v}"));
1:before: V1 { Value = 1 },V1 { Value = 2 },V1 { Value = 3 },V1 { Value = 4 },V1 { Value = 5 }
1:after : V1 { Value = 🐁 },V1 { Value = 2 },V1 { Value = 3 },V1 { Value = 🐈 },V1 { Value = 🐒 }
Index でいうところの
0: 反映される(インデクサから直接プロパティ変更)
1: 反映されない(値渡し+プロパティ変更)
2: 反映されない(値渡し+インスタンス変更)
3: 反映される(参照渡し+プロパティ変更)
4: 反映される(参照渡し+インスタンス変更)
となります。
参照型(可変)
例えばこういったクラス(参照型)があったとするじゃないですか。
record class V2(string Value) {
public string Value {get;set;} = Value;
}
(※record class はデフォルトで get; init; で読み取り専用なのでわざわざ書き換えられる様にしている)
次の様な操作をするとどうなるでしょうか?
V2[] array = [new("1"), new("2"), new("3"), new("4"), new("5")];
Console.WriteLine($"2:before: {ToString(array)}");
int i = 0;
{
//0: 配列のインデクサは参照戻り値
array[i++].Value = "🐁";
}
{
// 代入(値渡し)
{
var v = array[i++];
//1: プロパティを変更
v.Value = "🐄";
}
{
var v = array[i++];
//2: インスタンスを更新
v = v with {
Value = "🐅",
};
}
}
{
// ref ローカル変数 (参照渡し)
{
ref var v = ref array[i++];
//3: プロパティを変更
v.Value = "🐈";
}
{
ref var v = ref array[i++];
//4: インスタンスを更新
v = v with {
Value = "🐒",
};
}
}
Console.WriteLine($"2:after : {ToString(array)}");
string ToStringT>(T[] array) => string.Join(",", array.Select(v => $"{v}"));
2:before: V2 { Value = 1 },V2 { Value = 2 },V2 { Value = 3 },V2 { Value = 4 },V2 { Value = 5 }
2:after : V2 { Value = 🐁 },V2 { Value = 🐄 },V2 { Value = 3 },V2 { Value = 🐈 },V2 { Value = 🐒 }
Index でいうところの
0: 反映される(インデクサから直接プロパティ変更)
1: 反映される(値渡し+プロパティ変更)
2: 反映されない(値渡し+インスタンス変更)
3: 反映される(参照渡し+プロパティ変更)
4: 反映される(参照渡し+インスタンス変更)
となります。
参照型(不変)
例えばこういったクラス(参照型)があったとするじゃないですか。
record class V3(string Value);
C# でいう record class は不変な クラスレコードです。
次の様な操作をするとどうなるでしょうか?
V3[] array = [new("1"), new("2"), new("3"), new("4"), new("5")];
Console.WriteLine($"3:before: {ToString(array)}");
int i = 0;
{
//0: [直接編集不可] 配列のインデクサは参照戻り値
i++;
// array[i++].Value = "🐁";
}
{
// 代入(値渡し)
{
var v = array[i++];
//1: [直接編集不可]プロパティを変更
// v.Value = "🐄";
}
{
var v = array[i++];
//2: インスタンスを更新
v = v with {
Value = "🐅",
};
}
}
{
// ref ローカル変数 (参照渡し)
{
ref var v = ref array[i++];
//3: [直接編集不可] プロパティを変更
// v.Value = "🐈";
}
{
ref var v = ref array[i++];
//4: インスタンスを更新
v = v with {
Value = "🐒",
};
}
}
Console.WriteLine($"3:after : {ToString(array)}");
string ToStringT>(T[] array) => string.Join(",", array.Select(v => $"{v}"));
3:before: V3 { Value = 1 },V3 { Value = 2 },V3 { Value = 3 },V3 { Value = 4 },V3 { Value = 5 }
3:after : V3 { Value = 1 },V3 { Value = 2 },V3 { Value = 3 },V3 { Value = 4 },V3 { Value = 🐒 }
Index でいうところの
0: 許されない(インデクサから直接プロパティ変更)
1: 許されない(値渡し+プロパティ変更)
2: 反映されない(値渡し+インスタンス変更)
3: 許されない(参照渡し+プロパティ変更)
4: 反映される(参照渡し+インスタンス変更)
となります。
つまり表にまとめるとこう
項目 | 値型+可変 | 参照型+可変 | 参照型+不変 |
---|---|---|---|
インデクサから直接プロパティ変更 | ⭕ | ⭕ | – |
値渡し+プロパティ変更 | ❌ | ⭕ | – |
値渡し+インスタンス変更 | ❌ | ❌ | ❌ |
参照渡し+プロパティ変更 | ⭕ | ⭕ | – |
参照渡し+インスタンス変更 | ⭕ | ⭕ | ⭕ |
上記の動作から見て、 値型の プロパティの変更も インスタンスの変更も同様の挙動とみて良さそうです。
また、インデクサからの直接変更は 参照渡し による変更に間違いは無さそうです。
参照型+不変とすることで 参照型の特性である インスタンスを変更せずにプロパティの変更ができなくなり、値型の挙動と同じになることが確認できました。
値渡ししかない言語であればまず違いはわからないですね。
以上。