建设网站成本网站后台fpt
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:44
当前位置: 首页 > news >正文
建设网站成本,网站后台fpt,朝阳做网站公司,erp系统入门教程一. 值类型和引用类型
- 前言 (1). 分类 值类型包括#xff1a;布尔类型、浮点类型(float、double、decimal、byte)、字符类型(char)、整型#xff08;int、long、short等#xff09;、枚举(entum)、结构体(struct)。 引用类型#xff1a;数组、字符串(string)、类、接口…一. 值类型和引用类型
- 前言 (1). 分类 值类型包括布尔类型、浮点类型(float、double、decimal、byte)、字符类型(char)、整型int、long、short等、枚举(entum)、结构体(struct)。 引用类型数组、字符串(string)、类、接口、委托(delegate)。 (2).内存存储 值类型数据存放在栈stack中 引用类型地址存放栈stack中数据存放在堆heap中。 值类型变量声明后不管是否赋值都会在在栈中分配内存空间。引用类型声明时只在栈中分配内存用于存放地址并没有在堆上分配内存空间。
- 对象的传递 (1). 将值类型的变量赋值给另一个变量会执行一次赋值赋值变量包含的值。 (2). 将引用类型的变量赋值给另一个引用类型变量它复制的是引用对象的内存地址在赋值后就会多个变量指向同一个引用对象实例。 代码分享 Console.WriteLine(————————下面是值类型和引用类型赋值—————————–);//值类型赋值int a 0;int b a;Console.WriteLine(\(默认值 a{a},b{b});a 1;Console.WriteLine(\)修改a的值后 a{a},b{b});b 2;Console.WriteLine(\(修改b的值后 a{a},b{b});//引用类型赋值Student stu1 new Student();stu1.age 20;Student stu2 stu1;Console.WriteLine(\)默认值 stu1.age{ stu1.age}, stu2.age{stu2.age});stu1.age 30;Console.WriteLine(\(修改stu1.age的值后stu1.age{ stu1.age}, stu2.age{stu2.age});stu2.age 40;Console.WriteLine(\)修改stu2.age的值后 stu1.age{ stu1.age}, stu2.age{stu2.age}); 运行结果 3. 参数按值传递 (1). 对于值类型(age)传递的是该值类型实例的一个副本因此原本的值age并没有改变。 (2). 对于引用类型(Student stu)传递是变量stu的引用地址即stu对象实例的内存地址拷贝副本因此他们操作都是同一个stu对象实例。 代码分享 {Console.WriteLine(————————下面是参数按值传递—————————–);//值类型按值传递int age1 60;Utils.AddAge1(age1);Console.WriteLine(\(age{age1});//引用类型按值传递Student stu2 new Student();stu2.age 100;Utils.ReduceAge1(stu2);Console.WriteLine(\)age{stu2.age}); } public class Utils {public static void ReduceAge1(Student stu){stu.age - 10;Console.WriteLine(\(ReduceAge age{stu.age});}public static void AddAge1(int age){age 10;Console.WriteLine(\)AddAge age {age});}public static void ReduceAge2(ref Student stu){stu.age - 10;Console.WriteLine(\(ReduceAge age{stu.age});}public static void AddAge2(ref int age){age 10;Console.WriteLine(\)AddAge age {age});}} 运行结果 4. 参数按引用类型传递 不管是值类型还是引用类型可以使用ref或out关键字来实现参数的按引用传递。ref或out关键字告诉编译器方法传递的是参数地址而非参数本身。在按引用传递时方法的定义和调用都必须显式的使用ref或out关键字不可以省略否则会引起编译错误。 代码分享 {Console.WriteLine(————————下面是参数按引用传递—————————–);//值类型按值传递int age1 60;Utils.AddAge2(ref age1);Console.WriteLine(\(age{age1});//引用类型按值传递Student stu2 new Student();stu2.age 100;Utils.ReduceAge2(ref stu2);Console.WriteLine(\)age{stu2.age}); }public class Utils{public static void ReduceAge1(Student stu){stu.age - 10;Console.WriteLine(\(ReduceAge age{stu.age});}public static void AddAge1(int age){age 10;Console.WriteLine(\)AddAge age {age});}public static void ReduceAge2(ref Student stu){stu.age - 10;Console.WriteLine(\(ReduceAge age{stu.age});}public static void AddAge2(ref int age){age 10;Console.WriteLine(\)AddAge age {age});}} 运行结果 更多C后台开发技术点知识内容包括C/CLinuxNginxZeroMQMySQLRedisMongoDBZK流媒体音视频开发Linux内核TCP/IP协程DPDK多个高级知识点。 C/CLinux服务器开发高级架构师/C后台开发架构师免费学习地址 【文章福利】另外还整理一些C后台开发架构师 相关学习资料面试题教学视频以及学习路线图免费分享有需要的可以点击领取 5. string和其它引用类型的区别 (1). 在string字符串一开始s1地址指向是ypf因为s2s1所以s2地址也同样指向ypf当s1再次赋值lmr时堆中就会开辟出数据lmr而且ypf没有消失没有被覆盖。s1地址就指向lmrs2地址还是原来的ypf。 (2). 在引用类型数组上一开始arry1和arry2的地址都指向{1,2,3}当给arry1进行数据更改时由于是引用类型所以在{1,2,3}上面进行更改就会对arry2进行覆盖。 代码如下 {Console.WriteLine(————————下面是string和其它引用类型的区别—————————–);//string类型的测试string s1 ypf;string s2 s1;Console.WriteLine(\(s1{s1},s2{s2});//修改s1的值s1 lmr;Console.WriteLine(\)s1{s1},s2{s2});//其它引用类型的测试int[] arry1 new int[] { 1, 2, 3 };int[] arry2 arry1;Console.WriteLine(\(默认值arry1[0]{arry1[0]},arry1[1]{arry1[1]},arry1[2]{arry1[2]});Console.WriteLine(\)默认值arry2[0]{arry2[0]},arry2[1]{arry2[1]},arry2[2]{arry2[2]});arry1[2] 0;Console.WriteLine(\(修改后arry1[0]{arry1[0]},arry1[1]{arry1[1]},arry1[2]{arry1[2]});Console.WriteLine(\)修改后arry2[0]{arry2[0]},arry2[1]{arry2[1]},arry2[2]{arry2[2]});} 运行效果 string变化图如下 Array类型变化图如下 6. 拆箱和装箱 装箱是值类型向引用类型转换时发生的拆箱是引用类型向值类型转换时发生的。装箱是隐式的拆箱是显式的 代码分享 {Console.WriteLine(————————下面是拆箱和装箱—————————–);int a 123;object obj a; //装箱(隐式)Console.WriteLine(\(装箱后的结果obj{obj});int b (int)obj; //拆箱(显式)Console.WriteLine(\)拆箱后的结果b{b}); } 运行效果 7. 总结 (1). 值类型有更好的效率但不支持多态适合用作存储数据的载体。而引用类型支持多态适合用于定义程序的行为。 (2). 引用类型可以派生新的类型而值类型不能。 二. 深拷贝和浅拷贝
- 浅拷贝 创建一个新对象这个对象有着原始对象属性值的一份精确拷贝。如果属性是值类型和string类型拷贝的就是基本类型的值如果属性是引用类型拷贝的就是内存地址string类型除外所以修改其中一个对象就会影响到另一个对象。
- 深拷贝 将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象和原对象的修改不会相互影响.
- 二者区别 最根本的区别在于是否真正获取一个对象的复制实体,而不是引用,假设B复制了A修改A的时候看B是否发生变化 (1).如果B跟着也变了说明是浅拷贝拿人手短修改堆内存中的同一个值 (2).如果B没有改变说明是深拷贝自食其力修改堆内存中的不同的值 简单的来说 如果拷贝的时候共享被引用的对象就是浅拷贝如果被引用的对象也拷贝一份出来就是深拷贝。深拷贝就是说重新new一个对象然后把之前的那个对象的属性值在重新赋值给这个用户
- .Net中实现 (1).浅拷贝通过MemberwiseClone()方法实现. (2).深拷贝可以通过流的方式和反射的方式来实现,其中流的方式类前必须加 [Serializable], 反射的方式需要考虑的问题很多嵌套以及各种类型, 此处提供的方法并不完善. 代码分享 /// summary/// 克隆方法(基于浅拷贝)/// 用于实现ICloneable里方法当然你用来实现深拷贝也可以/// /summary/// returns/returnspublic object Clone(){return this.MemberwiseClone();}/// summary/// 克隆方法(基于深拷贝)/// 类前面必须加可序列化标志[Serializable]/// /summary/// returns/returnspublic object DeepClone1(){using (MemoryStream stream new MemoryStream()){BinaryFormatter bFormatter new BinaryFormatter();bFormatter.Serialize(stream, this);stream.Seek(0, SeekOrigin.Begin);return bFormatter.Deserialize(stream);}} 基于反射的深拷贝:(仅供参考不是很完善) public class Utils{ /// summary/// 基于反射的深拷贝/// 存在问题不是很好用/// /summary/// param nameobj/param/// returns/returnspublic static object DeepClone(Object obj){Type type obj.GetType();//对于没有公共无参构造函数的类型此处会报错object returnObj Activator.CreateInstance(type);FieldInfo[] fields type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);for (int i 0; i fields.Length; i){FieldInfo field fields[i];var fieldValue field.GetValue(obj);///值类型字符串枚举类型直接把值复制不存在浅拷贝if (fieldValue.GetType().IsValueType || fieldValue.GetType().Equals(typeof(System.String)) || fieldValue.GetType().IsEnum){field.SetValue(returnObj, fieldValue);}else{field.SetValue(returnObj, DeepClone(fieldValue));}}//属性PropertyInfo[] properties type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);for (int i 0; i properties.Length; i){PropertyInfo property properties[i];var propertyValue property.GetValue(obj);if (propertyValue.GetType().IsValueType || propertyValue.GetType().Equals(typeof(System.String)) || propertyValue.GetType().IsEnum){property.SetValue(returnObj, propertyValue);}else{property.SetValue(returnObj, DeepClone(propertyValue));}}return returnObj;}}
- 经过测试得出来一个结论 (1).对于浅拷贝所有值类型和string这个引用类型修改其中一个对象的值,不相互影响; 除了string以外的引用类型都相互影响; 类属于引用类型,修改类中的一个属性值被拷贝的另一个对象的属性值也会发生变化(与类中的属性值是什么类型没有关系). (2).对于深拷贝无论是值类型还是引用类型, 修改其中一个对象的值都不会相互影响。 代码分享 /// summary/// Video视频类/// /summary[Serializable]public class Video : ICloneable{public string Id { set; get; } // 视频编号public string Content { set; get; } // 视频内容public Listint ageList { set; get; }public VideoDetails vDetails { get; set; }/// summary/// 克隆方法(基于浅拷贝)/// 用于实现ICloneable里方法当然你用来实现深拷贝也可以/// /summary/// returns/returnspublic object Clone(){return this.MemberwiseClone();}/// summary/// 克隆方法(基于深拷贝)/// 类前面必须加可序列化标志[Serializable]/// /summary/// returns/returnspublic object DeepClone1(){using (MemoryStream stream new MemoryStream()){BinaryFormatter bFormatter new BinaryFormatter();bFormatter.Serialize(stream, this);stream.Seek(0, SeekOrigin.Begin);return bFormatter.Deserialize(stream);}}}/// summary/// 视频详情类/// /summary[Serializable]public class VideoDetails{public string videoUrl { get; set; }public int videoPic { get; set; }public VideoDetails(string myVideoUrl, int myVideoPic){this.videoUrl myVideoUrl;this.videoPic myVideoPic;}} 测试代码 #region 浅拷贝{Console.WriteLine(——————————-下面是基于浅拷贝————————————);Video v1 new Video(){Id 001,Content 西游记,ageList new Listint() { 000 }, //List是引用类型vDetails new VideoDetails(H:\DesignMode, 1111) //类也是引用类型};Video v2 (Video)v1.Clone();Console.WriteLine(\(v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v1.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});//修改v1的值,v2中的属性是否变化要分情况讨论的v1.Content 水浒传;v1.ageList[0] 111;v1.vDetails.videoUrl H:\XXXXXXX;v1.vDetails.videoPic 22222;Console.WriteLine(\)v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v2.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});}#endregion#region 深拷贝1(流的模式){Console.WriteLine(——————————-下面是基于深拷贝1————————————);Video v1 new Video(){Id 001,Content 西游记,ageList new Listint() { 000 },vDetails new VideoDetails(H:\DesignMode, 1111)};Video v2 (Video)v1.DeepClone1();Console.WriteLine(\(v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v1.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});//修改v1的值,v2不变v1.Content 水浒传;v1.vDetails.videoUrl H:\XXXXXXX;v1.vDetails.videoPic 22222;Console.WriteLine(\)v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v2.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});}#endregion 运行结果 三. 原型模式详解
- 背景 在有些系统中存在大量相同或相似对象的创建问题如果用传统的构造函数来创建对象会比较复杂且耗时耗资源用原型模式生成对象就很高效就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。
- 定义和特点 定义如下用一个已经创建的实例作为原型通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效根本无须知道对象创建的细节。例如Windows 操作系统的安装通常较耗时如果复制就快了很多。
- 具体实现 (1). 模式结构 A. 抽象原型类规定了具体原型对象必须实现的接口eg.Net 中的ICloneable。 B. 具体原型类实现抽象原型类的 clone() 方法它是可被复制的对象。 C. 访问类使用具体原型类中的 clone() 方法来复制新的对象。 结构图如下 (2). 使用场景 有一块视频我需要1个一模一样的并且我还需要1个除了路径不同其它都相同的视频这个时候可以使用原型模式哦。 (3). 代码实操 相关类 /// summary/// Video视频类/// /summary[Serializable]public class Video : ICloneable{public string Id { set; get; } // 视频编号public string Content { set; get; } // 视频内容public Listint ageList { set; get; }public VideoDetails vDetails { get; set; }/// summary/// 克隆方法(基于浅拷贝)/// 用于实现ICloneable里方法当然你用来实现深拷贝也可以/// /summary/// returns/returnspublic object Clone(){return this.MemberwiseClone();}/// summary/// 克隆方法(基于深拷贝)/// 类前面必须加可序列化标志[Serializable]/// /summary/// returns/returnspublic object DeepClone1(){using (MemoryStream stream new MemoryStream()){BinaryFormatter bFormatter new BinaryFormatter();bFormatter.Serialize(stream, this);stream.Seek(0, SeekOrigin.Begin);return bFormatter.Deserialize(stream);}}}/// summary/// 视频详情类/// /summary[Serializable]public class VideoDetails{public string videoUrl { get; set; }public int videoPic { get; set; }public VideoDetails(string myVideoUrl, int myVideoPic){this.videoUrl myVideoUrl;this.videoPic myVideoPic;}}测试代码 #region 01-完全相同视频的拷贝{Console.WriteLine(——————————- 01-完全相同视频的拷贝————————————);Video v1 new Video(){Id 001,Content 西游记,ageList new Listint() { 000 },vDetails new VideoDetails(H:\DesignMode, 1111)};Video v2 (Video)v1.DeepClone1(); //深拷贝Console.WriteLine(\(v1: Id{v1.Id},Content{v1.Content},ageList[0]{ v1.ageList[0]},Url{v1.vDetails.videoUrl},videoPic{v1.vDetails.videoPic});Console.WriteLine(\)v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v2.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});}#endregion#region 02-相似视频的拷贝{Console.WriteLine(——————————-02-相似视频的拷贝————————————);Video v1 new Video(){Id 001,Content 西游记,ageList new Listint() { 000 },vDetails new VideoDetails(H:\DesignMode, 1111)};Video v2 (Video)v1.DeepClone1(); //深拷贝Console.WriteLine(\(v1: Id{v1.Id},Content{v1.Content},ageList[0]{ v1.ageList[0]},Url{v1.vDetails.videoUrl},videoPic{v1.vDetails.videoPic});//相似视频的拷贝,只需要简单修改即可v2.vDetails.videoUrl F:\newVideo;Console.WriteLine(\)v2: Id{v2.Id},Content{v2.Content},ageList[0]{ v2.ageList[0]},Url{v2.vDetails.videoUrl},videoPic{v2.vDetails.videoPic});}#endregion 运行结果 4. 使用场景 (1). 对象之间相同或相似即只是个别的几个属性不同的时候。 (2). 对象的创建过程比较麻烦但复制比较简单的时候。 原文链接第三节: 值类型与引用类型、深拷贝与浅拷贝、原型模式详解 - Yaopengfei - 博客园
- 上一篇: 建设网站步骤搭建网站团队计划
- 下一篇: 建设网站出现400错误网站出租建设
相关文章
-
建设网站步骤搭建网站团队计划
建设网站步骤搭建网站团队计划
- 技术栈
- 2026年03月21日
-
建设网站不会写代码网站建设哪个好一些
建设网站不会写代码网站建设哪个好一些
- 技术栈
- 2026年03月21日
-
建设网站报价安徽网络公司排名
建设网站报价安徽网络公司排名
- 技术栈
- 2026年03月21日
-
建设网站出现400错误网站出租建设
建设网站出现400错误网站出租建设
- 技术栈
- 2026年03月21日
-
建设网站存在的问题建筑模板尺寸及价格
建设网站存在的问题建筑模板尺寸及价格
- 技术栈
- 2026年03月21日
-
建设网站的费用明细wordpress菜单栏添加
建设网站的费用明细wordpress菜单栏添加
- 技术栈
- 2026年03月21日
