6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[C#] structは全フィールドがゼロ初期化された場合でも正しい値になるときのみ使用すること

Last updated at Posted at 2025-12-16

言いたいこと

C#の値型は、default(T)や配列確保時、フィールド未初期化時など、
「全フィールドがゼロやnullで初期化された状態」
になる。これはstructを使用する上で、避けることができない制約である。

このときの値が
「表現したい値集合の中に必ず含まれ、不変条件を破らない」
ときのみ、値型を採用することをおすすめする。

例えば、「非ゼロの32bit符号なし整数値」をあらわす値型を作成するとき、

struct NotZeroUInt32
{
    public uint AsUInt32 { get; }
    public NotZeroUInt32(uint val)
    {
        if (val == 0) throw new ArgumentOutOfRangeException(nameof(val));
        AsUInt32 = val;
    }
}

これではいけない。
default(NotZeroUInt32).AsUInt32がゼロになってしまうからだ。
もし、こうした形でしか表せないのであれば、この型をstructで実装することをあきらめたほうがいい。

今回の場合は、回避方法があって、

struct NotZeroUInt32
{
    uint ValueMinusOne { get; }
    public uint AsUInt32 => ValueMinusOne + 1U;
    public NotZeroUInt32(uint val)
    {
        if (val == 0) throw new ArgumentOutOfRangeException(nameof(val));
        ValueMinusOne = val - 1U;
    }
}

とすればよい。この場合、default(NotZeroUInt32).AsUInt32は1になり、これは不変条件を破らない。
(値型はIEquatable<T>を実装すべき云々もあるけど、今回の主題ではないので省略)

struct Int32Range
{
    public int Max { get; }
    public int Min { get; }
    
    public Int32Range(int max, int min) { ... }
}

これもdefault(Int32Range)とすると、MaxMinがゼロになる。
採用したい不変条件がMin <= Maxであればかまわないかもしれないが、Min < Maxであればstructでは素直には表現できないことになる。

結論

structはヒープ割り当てを避けられ大量生成時に有利なため、採用したくなる場面がある。
その代償として、このdefault制約を受け入れなくてはならない。
パフォーマンスの制約上、目をつぶって使わざるを得ない場合もあるが、通常は「全フィールドがゼロ初期化された状態」が正しい値である場合にのみ値型にするというルールに従うことをおすすめする。

これに違反した場合、「IsDefault」などというプロパティを作り、この型の値を受け取るメソッド内でこのプロパティがtrueならArgumentExceptionを投げるようなことをする必要がでてくる。参照型のnullチェックと変わりないように思うかもしれないが、APIの使い方を型から読み取れなくなってしまうのは大きな問題だ。

値型から参照型に後から切り替えるのはかなり面倒な作業になるので、最初の設計時に注意することが肝心になる。

余計な付け足し

最後に、この記事は

に触発されて書いたものだ。
ゲームはパフォーマンスに厳しい場面が数多くあると思う。Unityに関して書いてあるこの記事に意見する気はまったくないことを付けくわえておく。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?