C#值类型,作为函数形参,形参被修改,不影响原值。
这是我们在初始学习编程时需要记住的内容,我们也是一直这样践行的。
先说结论:这是不准确的。
为什么提出这样看似很浅显的问题,是因为有次我在使用ArraySegment<byte>
值类型时,有感而发。
这是一个托管的值类型,表示array的一个片断, 在用做websocket接收数据的载体时我发现每次值传递后, 这个ArraySegment<byte>
貌似发生了变化。这勾起了我的探究欲。
我们做一个简单的实验, 来证明【值类型作为函数形参, 形参被修改,不影响原值】不准确。
struct Slice {public Array Array { get; set; }public int Offset { get; set; }public int Count { get; set; }}class Program{static void Main(string[] args){var slice = new Slice { Array = Array.CreateInstance(typeof(int), 5)};Test(slice);foreach(var i in slice.Array){Console.WriteLine(i); }Console.ReadLine();}// 值类型传参,值传给tmp变量static void Test(Slice tmp){tmp.Array.SetValue(1,1);tmp.Offset = 1;tmp.Count = 1;}}// 输出 0 1 0 0 0
slice变量的引用类型属性体现了变化,值类型Offset Count属性不会变化。这个简单的Demo告诉我们:
大部分情况下:“值类型作为函数形参,形参被修改,不影响原值”, 但是如果修改的是值类型的引用类型字段,原值类型照样能体现修改。
归根到底由值类型和引用类型的特性决定:
值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中;
宽泛地讲:函数传参,都是值传递(拷贝), 只是引用类型传递的是原对象的引用或地址值。
本篇文章没啥干货,算是日常小记吧,各大佬轻喷。
基础不牢 地动山摇
面试官:实现一个带值变更通知能力的Dictionary
你管这叫"线程安全"?
你怕是对MD5算法有误解
String是一个奇怪的引用类型
难缠的布隆过滤器,这次终于通透了