Search code examples
c#call-by-value

c# passing class type member as parameter works as call by value


as i know class type parameter is always passed as reference. but whenever i pass a class type variable which is class member as parameter. it always works like call by value.

public class MapGenerator : MonoBehaviour
{
   [SerializeField]
    private List<MapEntity> stageTerrains = new List<MapEntity>();
    private MapEntity stageTerrain = new MapEntity();

    private void Start()
    {
        RandomChoice(stageTerrains);
    }


    public void RandomChoice(MapEntity mapEntity)
    { 
        mapEntity = stageTerrains[Random.Range(0,selectedList.Count)];
        Print(mapEntity);  //it always works well 
        Print(stageTerrain);  // always print null
    }
}

so i put an ref keyword to parameter and it works as call by reference

public class MapGenerator : MonoBehaviour
{
   [SerializeField]
    private List<MapEntity> stageTerrains = new List<MapEntity>();
    private MapEntity stageTerrain = new MapEntity();

    private void Start()
    {
        RandomChoice(ref stageTerrains);
    }


    public void RandomChoice(ref MapEntity mapEntity)
    { 
        mapEntity = stageTerrains[Random.Range(0,selectedList.Count)];
        Print(mapEntity);  //it always works well 
        Print(stageTerrain);  // print well too 
    }
}

i wonder why passing class type member as parameter is worked like call by value


Solution

  • From the ref documentation

    When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. The ref keyword makes the formal parameter an alias for the argument, which must be a variable.

    So I'll try to explain the makes the formal parameter an alias as simple as possible.

    Without ref

    Imagine the stageTerrain from private MapEntity stageTerrain = new MapEntity(); as a box holding an address.

    Imagine the mapEntity from public void RandomChoice(MapEntity mapEntity) as another NEW box.

    • If you change a property of the mapEntity before assigning a new object, it will also change the value of the calling variable.

    When you call the RandomChoice the mapEntity is a new box holding the same memory address as the stageTerrain box.

    Now mapEntity = stageTerrains[Random.Range(0,selectedList.Count)]; will assign the selected value only to the New box.

    With ref

    Imagine the mapEntity from public void RandomChoice(ref MapEntity mapEntity) as an alias for an already existing box that will hold the memory reference just with a different name. (thus the alias statement)

    When you call the RandomChoice the mapEntity is the stageTerrain box.