作为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过程中的感触体会
如果一些专业术语使用不当或是观念不正确,还请海涵指教