合肥大型网站制网站建设 爱诚科技

当前位置: 首页 > news >正文

合肥大型网站制,网站建设 爱诚科技,discuz 企业网站,手机最新发布会文章目录 一、值类型和引用类型汇总补充1、值类型和引用类型汇总2、值类型和引用类型的区别3、简单的判断值类型和引用类型 二、变量的生命周期与性能优化1、栈和堆的区别2、变量生命周期3、垃圾回收#xff08;GC#xff09;机制4、代码示例与优化4.1. 临时… 文章目录 一、值类型和引用类型汇总补充1、值类型和引用类型汇总2、值类型和引用类型的区别3、简单的判断值类型和引用类型 二、变量的生命周期与性能优化1、栈和堆的区别2、变量生命周期3、垃圾回收GC机制4、代码示例与优化4.1. 临时变量的生命周期与回收4.2. 临时变量的性能问题每次创建新变量4.3. 性能优化减少不必要的变量创建4.4. 使用成员变量或者静态变量 5、其他注意事项6、总结 三、值类型和引用类型组合使用1、结构体中的值类型和引用类型2、类中的值类型和引用类型3、数组中的值类型和引用类型4、结构体继承接口4.1 示例4.2装箱拆箱4.3 性能考虑 5、简单记忆口诀 专栏推荐完结 一、值类型和引用类型汇总补充 1、值类型和引用类型汇总 我们学了很多新的值类型和引用类型这里列个表全部分类一下方便大家查看对比 类型类别类型描述值类型byte无符号 8 位整数 (范围0 到 255)ushort无符号 16 位整数 (范围0 到 65,535)uint无符号 32 位整数 (范围0 到 4,294,967,295)ulong无符号 64 位整数 (范围0 到 18,446,744,073,709,551,615)sbyte有符号 8 位整数 (范围-128 到 127)short有符号 16 位整数 (范围-32,768 到 32,767)int有符号 32 位整数 (范围-2,147,483,648 到 2,147,483,647)long有符号 64 位整数 (范围-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807)float单精度浮点数 (32 位范围大约为 ±1.5 x 10^−45 到 ±3.4 x 10^38)double双精度浮点数 (64 位范围大约为 ±5.0 × 10^−324 到 ±1.7 × 10^308)decimal高精度十进制数128 位用于财务和其他需要高精度的应用char单一字符 (16 位 Unicode 字符)bool布尔值 (true 或 false)enum枚举类型定义一组命名常数值struct结构体类型可以包含字段、方法、属性等常用于表示值对象引用类型string字符串类型表示文本实际上是 char[] 的封装array数组类型可以是任何数据类型的集合class类类型用于定义对象的蓝图interface接口类型用于定义类和结构体的契约delegate委托类型用于定义引用方法的类型 2、值类型和引用类型的区别 值类型 存储直接存储数据值。分配方式在栈stack上分配内存。赋值行为赋值时会复制数据两个变量的修改不会相互影响。 引用类型 存储存储的是数据的引用即指向内存中数据的地址。分配方式在堆heap上分配内存。赋值行为赋值时会复制引用两个变量指向同一内存位置修改其中一个会影响另一个。
3、简单的判断值类型和引用类型 可以看到前面有这么多的数据类型记不住怎么办 我们可以在编辑器按F12或者ctrl鼠标左键点击进去类型的内部查看信息 如果是class类就是引用类型如果是struct结构体就是值类型 比如int就是值类型 string就是引用类型 二、变量的生命周期与性能优化 1、栈和堆的区别 C# 中的变量存储在栈Stack和堆Heap上这取决于变量的类型 值类型Value Types包括 int、double、struct 等。值类型的变量直接存储数据本身它们通常被分配在栈上。当超出作用域时栈上的值类型会自动被回收。引用类型Reference Types包括 class、string、array、delegate 等。引用类型的变量存储的是指向实际数据在堆上的对象的引用地址。当引用类型变量超出作用域时栈上的引用会被回收但堆上的对象不会立即被销毁而是会等待垃圾回收GC机制回收。 2、变量生命周期 栈上值类型变量当栈上的值类型变量超出作用域时它会被立即销毁。堆上引用类型变量引用类型的变量在栈上存储的是对象的地址当栈上的引用类型变量超出作用域时指向堆上对象的引用会被清除但堆上的对象不会立刻被销毁只有在垃圾回收GC时它们才会被回收。 3、垃圾回收GC机制 垃圾回收C# 使用垃圾回收机制来自动管理内存特别是对堆上的对象进行内存管理。当对象没有任何引用时它会被垃圾回收器标记为垃圾并释放其占用的内存空间。值类型的回收栈上存储的值类型变量会在超出作用域后自动销毁不需要显式回收。引用类型的回收栈上存储的引用会在超出作用域时被回收但堆上的对象仍然需要垃圾回收器来管理。垃圾回收器会在堆上标记不再使用的对象并释放内存。 4、代码示例与优化 4.1. 临时变量的生命周期与回收 C# 中当一个临时变量如局部变量超出其作用域时它会被销毁特别是在语句块如函数、条件语句、循环语句等执行结束时栈上的局部变量会自动回收。 示例 1 void Example() {int i 5; // 局部变量 i } // 变量 i 超出作用域后会被销毁当 Example 方法执行完后i 超出了作用域栈上分配给 i 的内存会被回收。 下面这里会报错的原因就是栈是先进后出原则{}包裹语句块执行完成i2就被回收了所以外面打印不到i2内容
4.2. 临时变量的性能问题每次创建新变量 在某些情况下频繁创建临时变量可能会带来性能上的开销尤其是在循环中。例如 示例 2性能问题 while (true) {int i 1; // 每次循环都会创建新的 i }每次进入循环时int i 都会在栈上分配内存循环执行多次时会频繁地分配和销毁 i这会带来一定的性能开销。 4.3. 性能优化减少不必要的变量创建 为了避免每次循环都重新创建新的变量可以将变量声明移到循环外部。这样变量只会被创建一次循环内部只修改变量的值而不需要反复创建。 优化方法 1 int i 1; // 移动到循环外部减少变量创建次数 while (true) {i 1; // 只是赋值避免每次循环都重新创建变量 }这样i 只会在循环外部创建一次而每次循环只需要修改它的值不会进行重复的内存分配和回收。 4.4. 使用成员变量或者静态变量 如果变量在多个方法或类实例之间共享你可以考虑将变量声明为 成员变量 或 静态变量。这可以避免频繁创建临时变量提高性能。 优化方法 2成员变量 class Test {int i; // 成员变量public void TestMethod(){while (true){i 1; // 只修改成员变量的值}} }优化方法 3静态成员变量 class Test {static int i; // 静态成员变量public void TestMethod(){while (true){i 1; // 只修改静态变量的值}} }成员变量如果 i 只是与某个对象的状态相关可以将 i 声明为成员变量。静态变量如果 i 在所有对象之间共享可以将其声明为静态变量。注意静态变量是类级别的而非实例级别的。 5、其他注意事项 静态变量与垃圾回收静态变量的生命周期与应用程序的生命周期相同在整个程序运行期间它们会一直存在直到程序结束时才会被垃圾回收。避免不必要的内存分配在高频率执行的循环中尽量避免在每次循环中创建新变量尤其是值类型。可以考虑将变量移到循环外部或者使用静态变量和成员变量。 6、总结 值类型存储在栈上超出作用域后会自动回收。引用类型存储在堆上栈上的引用超出作用域时会被回收但堆上的对象直到垃圾回收器执行时才会被回收。性能优化减少不必要的内存分配和销毁避免在循环中频繁创建局部变量。可以通过将变量移到循环外部或使用成员变量、静态变量来优化性能。 三、值类型和引用类型组合使用 1、结构体中的值类型和引用类型 我们知道在C#中结构体 (struct) 是值类型存储在栈上而引用类型如 string存储在堆上。那么结构体中的字段算是值类型还是引用类型呢尤其是如何区分这两种类型的内存分配方式。 结构体 (struct) 本身是值类型因此当你复制结构体时结构体内的所有字段无论是值类型还是引用类型都会被复制而不是对象的实际内容。 结构体中的值类型字段存储的是实际的值并且这个值直接存储在结构体的实例内存区域中。如果结构体作为方法参数传递它会被 复制因此对结构体字段的修改不会影响原始结构体。 结构体中的引用类型字段这些字段存储的是对堆中对象的引用即地址。即使结构体是值类型结构体内部的引用类型字段仍然会引用堆中的对象。当结构体复制时引用类型字段的引用会被复制因此多个结构体实例可以引用同一个堆对象。
2、类中的值类型和引用类型 类class是引用类型意味着它的实例会在堆上分配内存变量存储的是对对象的引用地址而不是对象的实际内容。 类中的值类型字段在类中的值类型字段如 int、float 等存储的是实际的值这些值存储在对象的内存区域。因为类本身是引用类型所以这些值会随着类的对象一起存储在堆上。 类中的引用类型字段这些字段存储的是对堆中对象的引用。当引用类型字段被赋值时实际上是将引用的地址传递给另一个变量因此修改一个引用类型字段会影响所有引用该对象的变量。
3、数组中的值类型和引用类型 数组本身是引用类型这意味着当你创建一个数组时实际上是创建了一个指向堆heap中数据的引用。栈stack上只保存了这个引用而实际的数据存储在堆中。类中的值类型字段如果数组是值类型的数组如 int[], double[]那么数组中的每个元素都是独立的值类型实例它们直接存储在数组所在的堆内存中。类中的引用类型字段如果数组是引用类型的数组如 string[], object[]那么数组中的每个元素都是引用指向堆中某个对象的实际位置。 4、结构体继承接口 在C#中结构体struct可以实现接口尽管结构体是值类型而接口是引用类型。 4.1 示例 比如我们新增一个结构体继承接口 interface ITest { int Value {get;set;} }struct TestStruct : ITest {private int value;public int Value { get value; set this.value value; } }根据里氏替换原则父类可以装子类。所以我们可以用接口容器父类装载结构体子类。 TestStruct ts1 new TestStruct(); ts1.Value 1; Console.WriteLine(ts1.Value);TestStruct ts2 ts1; ts2.Value 2; Console.WriteLine(ts1.Value); Console.WriteLine(ts2.Value);ITest it1 ts1;//装箱 ITest it2 it1; it2.Value 100; Console.WriteLine(it1.Value); Console.WriteLine(it2.Value);结果 根据结果我们可以发现后面it1 it2的值打印都是100相当于我们强行把值类型变成了引用类型。 4.2装箱拆箱 用接口容器装载结构体存在装箱拆箱。当你将一个实现了接口的结构体赋给接口类型的变量时会发生装箱操作即将值类型转换为引用类型。相反的过程称为拆箱。 TestStruct ts1 new TestStruct(); ITest it1 ts1;//装箱 TestStruct ts3 (TestStruct)it1;//拆箱4.3 性能考虑 频繁的装箱和拆箱会对性能产生负面影响尤其是在循环或大量数据处理的情况下。为了避免这种性能问题你可以考虑以下策略 使用类而不是结构体如果需要频繁地将对象存储在接口容器中考虑使用类而非结构体以避免装箱开销。减少装箱次数尽量减少不必要的装箱操作例如通过缓存已经装箱的对象。泛型使用泛型可以避免装箱。例如List 可以持有值类型而不发生装箱。 5、简单记忆口诀 值类型跟大哥走引用类型很自我 专栏推荐 地址【从零开始入门unity游戏开发之——C#篇】【从零开始入门unity游戏开发之——unity篇】【制作100个Unity游戏】【推荐100个unity插件】【实现100个unity特效】【unity框架开发】 完结 赠人玫瑰手有余香如果文章内容对你有所帮助请不要吝啬你的点赞评论和关注你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法也欢迎评论私信告诉我哦 好了我是向宇https://xiangyu.blog.csdn.net 一位在小公司默默奋斗的开发者闲暇之余边学习边记录分享站在巨人的肩膀上通过学习前辈们的经验总是会给我很多帮助和启发如果你遇到任何问题也欢迎你评论私信或者加群找我 虽然有些问题我也不一定会但是我会查阅各方资料争取给出最好的建议希望可以帮助更多想学编程的人共勉~