• 关于C#编程中引用与值类型赋值的一些容易犯错的地方


    值类型与引用类型的区别在于:值类型在赋值的时候是拷贝值,引用类型在赋值的时候的拷贝引用。记住这一个原则,我们再来分析一些具体情况:

     1             PointStruct pt1 = new PointStruct(2,2);
     2             PointStruct pt2 = pt1;
     3             PointStruct[] ptsArray = new PointStruct[3];
     4             ptsArray[0] = pt1;
     5             ptsArray[1] = pt2;
     6             List<PointStruct> ptsList = new List<PointStruct>();
     7             ptsList.Add(pt1);
     8             ptsList.Add(pt2);
     9             List<PointStruct> pts2List = new List<PointStruct>();
    10             pts2List.AddRange(ptsArray);
    11 
    12             List<PointStruct> pts3List = pts2List;
    13 
    14             Console.WriteLine("值类型的数组,原始值:");
    15             Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
    16             Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
    17                 ptsArray[0].X, ptsArray[0].Y, ptsArray[1].X, ptsArray[1].Y));
    18             Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
    19                 ptsList[0].X, ptsList[0].Y, ptsList[1].X, ptsList[1].Y));
    20             Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
    21               pts2List[0].X, pts2List[0].Y, pts2List[1].X, pts2List[1].Y));
    22             Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
    23              pts3List[0].X, pts3List[0].Y, pts3List[1].X, pts3List[1].Y));
    24             pt2.X = 10;
    25             pt1.Y = -1;
    26             ptsArray[0].X = 100;
    27             ptsArray[1].Y = 30;
    28             ptsList[0] = new PointStruct(1000, 1000);
    29             pts2List[1] = new PointStruct(-1000, -1000);
    30             Console.WriteLine("值类型的数组,修改后:");
    31             Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
    32             Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
    33                 ptsArray[0].X, ptsArray[0].Y, ptsArray[1].X, ptsArray[1].Y));
    34             Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
    35             ptsList[0].X, ptsList[0].Y, ptsList[1].X, ptsList[1].Y));
    36             Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
    37                pts2List[0].X, pts2List[0].Y, pts2List[1].X, pts2List[1].Y));
    38             Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
    39            pts3List[0].X, pts3List[0].Y, pts3List[1].X, pts3List[1].Y));

    其中PointStruct是一个值类型,我们先看结果:

    从结果上可以看出来,值类型基本上都是各管各的,互不干扰,最后的pts2List与pts3List是同一个引用,所以修改其中任意一个是会影响另外一个的,数组,列表集合都会这样,因为其实就是同一个对象,只是取了2个名字而已,所以不管这个对象是否是值类型。

    我们再看下面的代码:

     1             PointReference pt1 = new PointReference(2, 2);
     2             PointReference pt2 = pt1;
     3             PointReference[] ptsArray = new PointReference[3];
     4             ptsArray[0] = pt1;
     5             ptsArray[1] = pt2;
     6             List<PointReference> ptsList = new List<PointReference>();
     7             ptsList.Add(pt1);
     8             ptsList.Add(pt2);
     9             List<PointReference> pts2List = new List<PointReference>();
    10             pts2List.AddRange(ptsArray);
    11 
    12             List<PointReference> pts3List = pts2List;
    13 
    14             Console.WriteLine("引用类型的数组,原始值:");
    15             Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
    16             Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
    17                 ptsArray[0].X, ptsArray[0].Y, ptsArray[1].X, ptsArray[1].Y));
    18             Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
    19                 ptsList[0].X, ptsList[0].Y, ptsList[1].X, ptsList[1].Y));
    20             Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
    21               pts2List[0].X, pts2List[0].Y, pts2List[1].X, pts2List[1].Y));
    22             Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
    23              pts3List[0].X, pts3List[0].Y, pts3List[1].X, pts3List[1].Y));
    24             pt2.X = 10;
    25             pt1.Y = -1;
    26             ptsArray[0].X = 100;
    27             ptsArray[1].Y = 30;
    28             ptsList[0] = new PointReference(1000, 1000);
    29             pts2List[1] = new PointReference(-1000, -1000);
    30             Console.WriteLine("引用类型的数组,修改后:");
    31             Console.WriteLine(string.Format("pt1:x:{0},y:{1},pt2:x:{2},y:{3}", pt1.X, pt1.Y, pt2.X, pt2.Y));
    32             Console.WriteLine(string.Format("ptsArray[0]:x:{0},y:{1},ptsArray[1]:x:{2},y:{3}",
    33                 ptsArray[0].X, ptsArray[0].Y, ptsArray[1].X, ptsArray[1].Y));
    34             Console.WriteLine(string.Format("ptsList[0]:x:{0},y:{1},ptsList[1]:x:{2},y:{3}",
    35              ptsList[0].X, ptsList[0].Y, ptsList[1].X, ptsList[1].Y));
    36             Console.WriteLine(string.Format("pts2List[0]:x:{0},y:{1},pts2List[1]:x:{2},y:{3}",
    37                pts2List[0].X, pts2List[0].Y, pts2List[1].X, pts2List[1].Y));
    38             Console.WriteLine(string.Format("pts3List[0]:x:{0},y:{1},pts3List[1]:x:{2},y:{3}",
    39            pts3List[0].X, pts3List[0].Y, pts3List[1].X, pts3List[1].Y));

    其中PointReference是引用类型,先看看结果:

    从结果上看pt1,pt2,ptsArray是相互影响的,因为PointReference是引用类型,另外ptsList是重新申请的一个类,只是添加了两个成员,成员是pt1,pt2,修改任意一个,也会影响这个ptsList,但是如果对ptsList的成员的X,Y是只读的,不能修改,所以只能重新赋值,在重新赋值后ptsList[0]都修改成1000,,1000了,但是其他的没有受影响,因为在修改以前里面存的引用是pt1,pt2的,在重新赋值后存的引用是重新new后的地址,自然不会对其他造成影响,然后pts2List也是一样的道理,修改pts2List是不会影响ptsList,但是会影响pts3List,因为他们的集合地址的引用是一样的,公用的存储空间。

    我希望从这个例子中可以帮我彻底的疏通我对值类型与引用类型在运用中遇到的难题。

    一些图示我就不画了,实际去分析我上传的例子就非常清楚了。

     https://files.cnblogs.com/files/monkeyZhong/ReferenceTypeVSValueTypeDemo.zip

  • 相关阅读:
    CF703D Mishka and Interesting sum
    CF697D Puzzles
    SCOI2017酱油记
    [BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏
    BZOJ4311:向量
    BZOJ4520: [Cqoi2016]K远点对
    BZOJ4555: [Tjoi2016&Heoi2016]求和
    [Codechef November Challenge 2012] Arithmetic Progressions
    agc040
    补题
  • 原文地址:https://www.cnblogs.com/monkeyZhong/p/4560974.html
Copyright © 2020-2023  润新知