当前位置 博文首页 > 无欲则刚的博客:值类型和引用类型

    无欲则刚的博客:值类型和引用类型

    作者:[db:作者] 时间:2021-09-10 18:58

    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告诉我们:

    大部分情况下:“值类型作为函数形参,形参被修改,不影响原值”, 但是如果修改的是值类型的引用类型字段,原值类型照样能体现修改。

    归根到底由值类型和引用类型的特性决定:

    值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中;

    宽泛地讲:函数传参,都是值传递(拷贝), 只是引用类型传递的是原对象的引用或地址值。

    cs