C# 如果class本身当参数传递是 call by reference , 那前面加上ref有何用呢?

作为IT邦的第一篇文章

就来开这个主题好了

public class ValueModel
{
    public int Value { get; set; }
}

public static void Assign(ValueModel model)
{
    model.Value = 10;
}

public static void Assign(int value)
{
    value = 10;
}

static void Main(string[] args)
{
    var model = new ValueModel();
    Assign(model);
    Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 10
    
    int value = 0;
    Assign(value);
    Console.WriteLine($"Value is {value}");//Value is 0

}

有点基本功的都能够知道如果是用class传入function,在function内修改的话,呼叫端的class也会一并修改

而 ValueType的 int则不会

所以如果希望int也有像reference的效果,加个ref就可以 如下

public static void Assign(ref int value)
{
    value = 10;
}

static void Main(string[] args)
{
    int value = 0;
    Assign(ref value);
    Console.WriteLine($"Value is {value}");//Value is 10
}

那今天的问题来了 如果ref用在ReferenceType上会怎样?

public static void Assign(ref ValueModel model)
{
    model.Value = 20;
}

static void Main(string[] args)
{
    {
        var model = new ValueModel();
        Assign(model);
        Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 10
    }
    {
        var model = new ValueModel();
        Assign(ref model);
        Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 20
    }
}

恩 看起来好像效果一样? 似乎没差别

在这个例子里面是这样没错,因为我们没有动到关键点 我们修改一下Assign的内容

public static void Assign(ValueModel model)
{
    model = new ValueModel();
    model.Value = 10;
}
public static void Assign(ref ValueModel model)
{
    model = new ValueModel();
    model.Value = 20;
}
static void Main(string[] args)
{
    {
        var model = new ValueModel();
        Assign(model);
        Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 0
    }
    {
        var model = new ValueModel();
        Assign(ref model);
        Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 20
    }
}

这样应该可以很容易地看出差异了

想像一下

若是没有加上ref的时候 其实方法呼叫时会将传入的物件贴上一个标签

修改资料是对这个标签上的物件做修改 而model = new ValueModel(); 其实则是将标签贴到new出来的物件上

所以去修改的时候 是修改新new出来的物件 而不是呼叫端传入的

那加上ref呢?

他是将外面呼叫端的标签传入 所以model = new ValueModel();是将外面的标签给贴到里面new出来的物件上

一开始呼叫端new的物件早就消失不见了
(没有任何方法可以存取他 因为它唯一的标签已经被撕掉 然後贴到方法内的物件上了)

我们可以再做个实验

static void Main(string[] args)
{
    {
        var model = new ValueModel();
        var oldmodel = model;
        Assign(ref model);
        Console.WriteLine($"ValueModel.Value is {model.Value}");//ValueModel.Value is 20
        Console.WriteLine($"oldmodel.Value is {oldmodel.Value}");//oldmodel.Value is 0
    }
}

在呼叫端的model被撕掉标签以前 我先给它贴上一个oldModel的标签

就可以清楚看见oldmodel其实根本没有被修改值

其实也可以用GetHashCode来检验是否为同一物件

好了~ 今天分享就此结束!

本人并非本科系出身,也没有受过什麽专业训练

都是自己在写Code过程中的感触体会

如果一些专业术语使用不当或是观念不正确,还请海涵指教


<<:  Leet Code 1. Two Sum

>>:  Leet Code 2. Two Numbers

Day16|什麽是 HEAD ?

在先前的章节里,我们可以常看见 HEAD 这个名词,它指的是什麽呢? // git 恢复文件到初始状...

Day12-D3 的 Tooltips

本篇大纲:tooltips 基础设定、tooltips 进阶应用 今天我们要来讲解算是D3最轻松简...

Day 12- --save-dev

今天要来说昨天 --save-dev的部分。 昨天文章指路-->https://ithelp....

请问服务路由器的IP地址怎麽算?

各位前辈们好,我想询问这题怎麽解~ 我查了很多资料还是不知道怎麽解 谢谢各位前辈 一部路由器有A、B...

成为工具人应有的工具包-24 SearchMyFiles

SearchMyFiles 今天来认识这个看名字判断应该是找自己的档案的工具? 可是这功能不是从 w...