C# 基礎からマスターまで — 第3回
class、struct、record、nullの安全性を理解する
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
C#では、データをclass、struct、recordで表現できます。 文法が似ていてもコピー方式と同一性の意味が異なるので目的に合わせて選択しなければならない。
classは参照形式です
public sealed class Player
{
public string Name { get; }
public int Health { get; private set; }
public Player(string name, int health)
{
Name = name;
Health = health;
}
}
Player first = new("Rose", 100);
Player second = first;
secondには、オブジェクト全体ではなく同じオブジェクトを指す参照がコピーされます。 一方でHealthを変えると他方でも変わった結果が見られる。
structは値型です
public readonly struct Position
{
public float X { get; }
public float Y { get; }
public Position(float x, float y)
{
X = x;
Y = y;
}
}
structを代入すると値がコピーされます。 座標や色のように小さく、1つの値として扱われるデータに似合う。
大きな構造はコピーコストが大きくなり、変更可能な構造は予想しにくい動作をすることができます。 structとは無条件高速ではない。
recordは値自体を比較します
public sealed record ItemKey(int Id, string Grade);
var a = new ItemKey(10, "Rare");
var b = new ItemKey(10, "Rare");
Console.WriteLine(a == b); // True
通常のクラスは基本的に同じ参照を比較しますが、recordは設定値が同じかどうかを比較します。 設定、コマンド、ネットワークメッセージなど、不変データに使用するのが良いです。
nullの可能性を型に表示する
Player? FindPlayer(int id)
{
return players.TryGetValue(id, out Player? player)
? player
: null;
}
Player? target = FindPlayer(10);
if (target is not null)
{
Console.WriteLine(target.Name);
}
nullable reference typeを使用すると、nullが可能な参照と非参照を区別できます。 警告を!にクリアする前に、本当にnullが不可能であるかどうかを再確認する必要があります。
class、struct、recordの選択は好みではありません。 オブジェクトのアイデンティティが重要なのか、値のコピーが自然なのか、不変のデータなのかを判断する必要があります。