Error CS1612: 変数ではないため、xxx の戻り値を変更できません

渡されたコピーを変更しようとした場合にエラーが出ます
エラー発生の理由がよくわからないケースになります
対処の方法についても考えていきましょう

C#でテスト

エラーになるコード

一見問題なく動作しそうですがダメですね

Square square = new Square();
square.Size.Height = 10.2f;

class Square
{
    public Size Size { get; set; }
}

struct Size
{
    public float Width;
    public float Height;
}

発生するエラー

展開した様子

エラーの箇所はコメントアウトして展開しています

プロパティに着目してください
getのブロック内に記述されているコードは、メソッドになると考えてください
つまりreturn される値は、structの場合、コピーされた値が返されることになります
なので、この値を変更しても元の値に影響があるわけではありません

プログラマーは代入したい意思がありますが、ダメですよね

[CompilerGenerated]
internal class Program
{
    private static void <Main>$(string[] args)
    {
        new Square();
    }
}

internal class Square
{
    [CompilerGenerated]
    private Size <Size>k__BackingField;

    public Size Size
    {
        [CompilerGenerated]
        get
        {
            return <Size>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Size>k__BackingField = value;
        }
    }
}

internal struct Size
{
    public float Width;

    public float Height;
}

対処

構造体をローカル変数に割り当てて、変数を「変更します
その後、代入することで対応します

Square square = new Square();

Size squareSize = square.Size;
squareSize.Height = 10.2f;
square.Size = squareSize;

class Square
{
    public Size Size { get; set; }
}

struct Size
{
    public float Width;
    public float Height;
}

展開した様子

[CompilerGenerated]
internal class Program
{
    private static void <Main>$(string[] args)
    {
        Square square = new Square();
        Size size = square.Size;
        size.Height = 10.2f;
        square.Size = size;
    }
}

internal class Square
{
    [CompilerGenerated]
    private Size <Size>k__BackingField;

    public Size Size
    {
        [CompilerGenerated]
        get
        {
            return <Size>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Size>k__BackingField = value;
        }
    }
}

internal struct Size
{
    public float Width;

    public float Height;
}

Unityでのサンプル

エラーになるコード

Unityのコードでも上記と同じことが言えます
次の簡略化したコードを確認してください

実際のコードはx, y, zを構造体Vecter3で宣言されていますが、ここでは学習のため省略しています

GameObject player = new GameObject();

player.transform.Position.x = 1.2f;

class GameObject
{
    public Transform transform = new Transform();
}

class Transform
{
    internal Position Position { get; set; }
}

struct Position
{
    public float x;
    public float y;
    public float z;
}

エラーになりますね

対処

一時変数を作成して、現在の値をコピーしておきます
xの値を更新します
更新した値を再度代入すればOKです

GameObject player = new GameObject();

Position tempPos = player.transform.Position;
tempPos.x = 1.2f;
player.transform.Position = tempPos;

class GameObject
{
    public Transform transform = new Transform();
}

class Transform
{
    internal Position Position { get; set; }
}

struct Position
{
    public float x;
    public float y;
    public float z;
}

まとめ

構造体を使い、プロパティ経由でアクセスした場合、このようにエラーになります
特にUnityでコードを書いている人は一度は出会うエラーではないでしょうか
構造体ではなく、クラスだと参照値が渡されるので問題がないのですが、Transformクラスは、UnityEngine内部に宣言されたコードなのでプログラマーが対処できないですね

理屈を理解するのは難しいでしょうが、学習のため一度は確認しておきましょう

C#,Unity

Posted by hidepon