C# 【無法修改XX返回值,因為它不是變量】


using UnityEngine;
using System.Collections;
using System.Xml.Linq;
using UnityEditor;
using System;

public class NewBehaviourScript : MonoBehaviour {

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

    class CTest{
        
        public MVec3 posx;
        public MVec3 pos { set; get; }//等同於下面的寫法->

        /*MVec3 dv = new MVec3 ();
        public MVec3 pos{
            set{ dv = value; }
            get{ return dv;}
        }*/

    }

    CTest otest;

    // Use this for initialization
    void Start () {
        otest = new CTest ();

        otest.pos.x = 10;
        otest.posx.x = 123;
        gameObject.transform.position.x = 10;

        Debug.Log ("ot.pos.x={0}" + otest.posx.x);

    }
    // Update is called once per frame
    void Update () {
        Vector3 vec3 = gameObject.transform.position;
    }
}

 編譯時出現如下錯誤:

 可以看到34行和36行都出現了編譯錯誤,而35行則正確編譯。原因分析:

C#中,reference類型變量存儲在堆上,value類型存儲在棧上。pos, posx, position都是值類型,為什么會有不同的編譯結果呢。區別在於 pos, position是屬性,posx是字段。具體分析如下:

32行:new了一個引用類型CTest的對像otest,這時在堆上為對象分配了一片內存,內存大小為pos的三個float和posx的三個float。

34行:由於pos是一個屬性,otest.pos將調用屬性的get方法,方法的調用是使用棧來進行的,get方法在棧上分配一個臨時變量temp來返回pos的的值。即otest.pos返回了一個分配在棧上的臨時變量的地址,而otest.pos.x = 10則是試圖對棧上臨時變量的X進行賦值。這個操作並非不合法,然而是沒有意義的,於是編譯器就阻止了我們的這個無意義操作,以避免隱患。同理36行。

明白了這個,就容易理解35行為什么是正確的了。otest.posx是一個正常的取地址操作,表示取出otest所在堆內存中的posx變量的地址,這個地址是對象的堆內存中的。

otest.posx.x = 10則是修改堆內存中posx的x的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM