《Effective C#》Item 6:区分值类型和引用类型

《Effective C#》Item 3:使用as和is操作符来做类型转换 在程序中,进行类型转换是常见的事。那么在C#中支持以前语言的类型转换方法,即用类型名进行强行转换,例如:object objTest = new NewType();NewType newValue = (NewType)objTest; 但是这样转换,有个严重的问题,就是在把objTest强转换成NewType类型对象的时候,这个过程是不安全的,因此需要用try-catch语句来 阅读详情

在C#中有两种类型的数据,一种是值类型数据,一种是引用类型数据。在编码的时候区分这两种类型数据,可以避免一些细小的编码错误。

 

首先说说什么类型是值类型,例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。除此外,如string,数组,以及用class定义的类型等都是引用类型。对于C#来说,很难罗列出所有类型进行一一分别,这需要自己在编码过程中进行分析总结。

 

为了更好地说明两种类型之间的区别,借用如下的表格来说明。

 

值类型

引用类型

内存分配地点

分配在栈中

分配在堆中

效率

效率高,不需要地址转换

效率低,需要进行地址转换

内存回收

使用完后,立即回收

使用完后,不是立即回收,等待GC回收

赋值操作

进行复制,创建一个同值新对象

只是对原有对象的引用

函数参数与返回值

是对象的复制

是原有对象的引用,并不产生新的对象

类型扩展

不易扩展

容易扩展,方便与类型扩展

 

通过如上细致对比,大家对于值类型和引用类型有个清楚的概念。

 

不过,无论是对于值类型还是引用类型来说,对于其作为函数参数或者返回值的时候,都是容易犯错误的地方。

 

对于值类型来说,当其作为函数参数的时候,希望在函数中被修改,那么直接如下操作是不能被修改的。

        public void Increment( int i )

        {

            i++;

        }

要想在函数中对传进去的参数做真正的修改,需要借助于ref这个关键字,那么正确的形式如下。

        public void Increment( ref int i )

        {

            i++;

        }

 

也就是说,如果需要在函数中对值类型参数进行修改,需要用ref或者out进行标识才能真正实现。

 

而对于引用类型来说,当其作为函数参数的时候,它所遇到的情况恰恰与值类型相反,即不希望在函数中被修改,举例如下。

        public void AddValue( MyType typValue )

        {

            typValue.Count = typValue.Count + 15;

        }

由于对于引用类型对象来说,其的赋值操作只是对原有对象的引用,因此在函数对其修改,实际上是直接修改了原有对象数据,这是很多情况不希望发生的(这里例如对数组或者DataTable操作这类)。

 

为了防止这种事发生,需要给此类型提供clone函数。例如对于如上的类型,可以入下实现。

    public class MyType:ICloneable

    {

        private int nCount = 0;

        public int Count

        {

            set{ nCount = value;}

            get{ return nCount;}

        }

        public MyType()

        {

        }

        public MyType( int Value)

        {

            nCount = Value;

        }

 

        #region ICloneable Members

 

        public object Clone()

        {

            // TODO:  Add MyType.Clone implementation

            return new MyType( nCount );

        }

 

        #endregion

    }

那么在调用的时候,用当前的对象的clone作为参数即可。

 

不过对于引用类型来说,提供一个clone函数不是一件容易的事情,尤其出现引用类型嵌套的时候,所以说去实现一个完全clone功能是件很费事又不讨好的活,这也就是在论坛中常说的深copy和浅copy的问题。话虽如此,如果对于前面所说的有个大概了解,相信实现也不是不可能。

 

在C#中,尤其自己定义类型的时候,常常由于是用struct来定义还是用class来定义,即是定义一个值类型还是一个引用类型呢。在这本书上给了几个判定条件,如果如下几点都满足的话,建议用struct来定义为值类型,否则用class定义为引用类型。

1.  这个类型是否主要为了数据存储;

2.  是否只通过属性来访问对象的数据成员;

3.  这个类型是否不会有子类型;

4.  在程序处理的时候不会把这个类型对象通过多态来处理。

 

总而言之,在C#中,就是把底层面的数据用值类型来处理,而包含复杂操作,需要进行扩展的数据用引用类型来处理。

《Effective C#》Item 21:用委托实现回调 委托属于C#中的新名词,它的应用也非常广泛,例如事件就是委托最简单而又直接的例子。 那么首先说说什么是委托,其实委托在用过C或者C++的人看来就是函数指针,不过使用C#的大多数人都没有用过这两门语言,因此对委托的理解不是很深,对于委托可以简单的从字面去理解,即“委托别人去执行某些操作”,也就是说执行一个操作,而这个操作过程自身并不知道,只是委托过来让你去执行而已。参看如下这个例子。 阅读详情

相关推荐

《Effective C#》Item 17:减少装箱(Boxing)和拆箱(Unboxing)操作

为了便于文章的开展,首先介绍装箱(Boxing)和拆箱(Unboxing)这两个名词。.Net的类型分为两种,一种是值类型,另一种是引用类型。这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上。那么如果要把一个值类型数据放到堆上,就需要装箱操作;反之,把一个放在堆上的值类型数据取出来,则需要进行拆箱操作。 例如,对于如下简单的装箱和拆箱操作语句。    int i

愚翁专栏 1万+

【Dart 教程系列第 49 篇】Dart 是值传递还是引用传递

Dart 是值传递还是引用传递。Dart 中 List 列表深拷贝的方式。

“Allen Su”的博客 2118

ControlItems.zip

上次上传的大家说有问题,是我没演示怎么使用items属性,我进行了改进, 大家可以看看类似datagrid的列属性items是怎么实现的。代码注视完整,开发平台vs2005,代码语言C#。

Hibernate中区分值(Value)类型和实体(Entity)类型

[color=red][align=center]有时候再用Hibernate的时候会抛出这样的一个异常“Unknown entity class:mypack.Address” 比如说,上面的情况是这样的 session.load(Address.class,new Long(1)); session.save(addr); package mypack; import...

hitxueliang的专栏 278

2023-2024深度学习框架之争——选pytorch还是tensorflow?

深度学习是人工智能领域的一个重要分支,它利用多层神经网络来模拟人类的学习和推理能力,解决各种复杂的问题,如图像识别、自然语言处理、语音识别、推荐系统等。深度学习框架是一种软件工具,它提供了构建、训练、测试和部署深度学习模型的便利,使得开发者和研究者可以更高效地进行深度学习的开发和应用。目前,市场上有许多不同的深度学习框架,如PyTorch、TensorFlow、Keras、MXNet、Caffe2等,它们各有优劣,适用于不同的场景和需求。

flchen_nchu的博客 6752

XCAT集群管理实战:从裸机到节点批量部署

在数据中心与HPC集群运维中,裸机配置与操作系统批量部署是关键环节。PXE引导、IPMI带外管理等基础技术为自动化装机提供了底层支持,而集群管理工具则将这些能力整合为可扩展的运维体系。XCAT作为一款开源集群管理工具,通过数据库驱动的方式统一管理DHCP、TFTP、HTTP等服务,实现从裸机发现、系统安装到电源控制的全流程自动化。本文从XCAT的核心设计出发,详细介绍了环境准备、安装配置、节点定义、镜像分发及常见问题排查,帮助运维人员快速构建高效的集群部署流程,降低规模化管理的复杂度。

weixin_30899023的博客 241

区分值类型和引用类型

 在C#中有两种类型的数据,一种是值类型数据,一种是引用类型数据。在编码的时候区分这两种类型数据,可以避免一些细小的编码错误。 首先说说什么类型是值类型,例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。除此外,如string,数组,以及用class定义的类型等都是引用类型。对于C#来说,很难罗列出所有类型进行一一分别,这需要自己

花落孤独 1487

深入探究贝叶斯网络(Bayesian Network):从基础原理到实际应用

贝叶斯网络,也称为信念网络或有向无环图模型,是一种概率图模型。它使用有向无环图(DAG)来表示随机变量之间的条件依赖关系。每个节点代表一个随机变量,边表示变量之间的条件依赖关系。贝叶斯网络作为一种强大的工具,通过结合概率论和图论,为复杂系统建模和推理提供了有效手段。无论是在医学诊断、故障检测还是自然语言处理等领域,它都展示了巨大的潜力。然而,其计算复杂度高、结构学习困难等挑战也需要我们在实际应用中不断优化算法和技术。希望通过本文,你能对贝叶斯网络有更深入的理解,并能够在实际项目中灵活应用这一强大工具。

qq_28791753的博客 5966

c#中的两种数据类型--值类型和引用类型

    我们都知道,c#的两大数据类型分别为值类型和引用类型。很多人或许闭着眼睛都能说出值类型包括简单类型、结构体类型和枚举类型,引用类型包括自定义类、数组、接口、委托等,但是当被问及到二者之间的联系和区别,什么时候用struct什么时候用class时,就常常混淆不清了。为此,了解值类型和引用类型的本质差异就变的很有必要了。值类型直接存储其值,变量本身就包含了其实例数据,而引用类型保存

Allen Chen的专栏 1568

ETL数据集成案例

一个典型的ETL数据集成案例是将多个来源的数据合并成一个数据集。假设有一个公司,该公司使用一些不同的系统来存储不同部门的数据,例如销售数据存储在一个CRM系统中,财务数据存储在一个ERP系统中,人力资源数据存储在一个HR系统中。为了更好地进行报告和分析,该公司决定将所有这些数据集成到一个数据仓库中。以下是实现这一目标的ETL过程的步骤:提取(Extract):首先,需要从每个系统中提取所需的数据。每个系统可能有不同的数据格式和结构,因此需要编写不同的提取程序或查询来提取数据。

runqu的博客 947

【华为OD技术面试手撕真题】3、小行星碰撞 | 手撕真题+思路参考+代码解析(C & C++ & Java & Python & JS)

小行星碰撞,本专栏更新每年华为OD机试的高频手撕代码题,每个题目都会使用五种语言进行解答(C & C++& Java & Python & JS),思路分析都非常详细, 实现最低的时间复杂度和高通过率,每个解题思路超过百字,内含各个编程语言的八股文面试题,欢迎大家订阅学习, 代码可以直接运行使用,全网限时最低价,持续更新

KJ.JK 8166

转:《Effective C#》Item 6:区分值类型和引用类型

转:http://blog.youkuaiyun.com/Knight94/archive/2006/07/01/861383.aspx在C#中有两种类型的数据,一种是值类型数据,一种是引用类型数据。在编码的时候区分这两种类型数据,可以避免一些细小的编码错误。 首先说说什么类型是值类型,例如:int、float、bool之类的基础类型,以及用struct定义的类型,如:DateTime。除此外,如

flyskylf的专栏 478

Cesium雷达追踪追踪(圆锥体效果)

【代码】Cesium雷达追踪追踪(圆锥体效果)

God's asylum的博客 2931

Effective C# Item6:明辨值类型和引用类型的使用场合

可能是受到Java的影响,我在转向C#后,一直没有注意区分过值类型和引用类型,不论是编写新代码还是重构旧代码时,如果发现有一些信息需要独立出来时,一直都是以新建类的方式进行,很少考虑使用结构体(我到目前为止,对结构体的理解还停留在C语言的层次)。     C#,或者说.NET,是区分值类型和引用类型的,这一点和C++以及Java都有区别。C++中传参都是以“传值”的方式进行,这种方式效率很高,但

尹自强.DoSomething() 514

全新YOLOv11一文弄懂 | YOLOv11网络结构解读 、yolov11.yaml配置文件详细解读与说明、模型训练参数详细解析 | 通俗易懂!入门必看系列!

本文全面介绍了YOLOv11目标检测算法,包含网络结构解析、yaml配置文件详解及训练教程。YOLOv11通过改进的C3k2f模块、SPPF和C2PSA注意力机制等创新设计,在COCO数据集上实现了比YOLOv8更优的性能。文章详细解读了yolov11.yaml配置文件的参数设置、主干网络(backbone)和头部网络(head)结构,并提供了完整的训练代码示例和参数说明。训练部分涵盖了模型选择、参数设置及优化技巧,包括epochs、batch size、学习率等关键参数的调整建议。最后总结了YOLOv11

Ai缝合怪、助力小伙伴高效发论文 3万+

Cesium教程(十七):淹没分析

淹没分析是根据某片区域的地形及洪水流量速度,动态模拟该地形区域水位逐渐上涨的淹没过程。该功能可适用于山区、丘陵等地形起伏较大区域,模拟洪水涨到安全限定高度的淹没过程,为防洪水救灾提供一定的参考。此外,还可以为河谷地带修建水利工程设计与选址提供参考依据。

WwLK123的博客 3006

Effective C# Item 6: Distinguish Between Value Types and Reference Types

Item 6: Distinguish Between Value Types and Reference Types 值类型还是引用类型?结构体还是类?我们应当用哪个?这不是C++,把所有的类型都定义为值类型,之后我们可以再为其创建引用;这也不是java,所有的类型都是引用类型。当我们创建类型的时候我们必须明确它的行为,这对我们正确能选择值还是引用非常重要。我们必须仔细推敲...

aijinyao5713的博客 151

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

《Effective C#》Item 9:区别和认识四个判等函数

.Net有四个判等函数?不少人看到这个标题,会对此感到怀疑。事实上确是如此,.Net提供了ReferenceEquals、静态Equals,具体类型的Equals以及==操作符这四个判等函数。但是这四个函数之间有细微的关系,改变其中一个函数的实现会影响到其他函数的操作结果。 首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数,对于它们俩来说,

愚翁专栏 9109

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C#学习资料《Effective C#》

Item 1: Always Use Properties Instead of Accessible Data Members《Effective C#》Item 1:用属性来访问类的私有成员http://blog.youkuaiyun.com/knight94/archive/2006/06/04/772886.aspxItem 2: Prefer readonly to const《Effectiv

SharpRose的专栏 1232

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Effective C# Item17: Minimize Boxing and Unboxing

Effective C# Item17: Minimize Boxing and Unboxing 在.Net中有值和引用两种类型,它们是不一致的。.Net Framework使用装箱和拆箱来做为二者之间的桥梁。通过装箱可以将一个值类型封装到一个无类型的引用型对象中。拆箱则是将引用类型从包装中释放出来。当我们需要将值类型当作引用类型一样来处理时,装箱和拆箱是必要的。但是这样...

aijinyao5713的博客 195
上一篇: 《Effective C#》Item 5:提供一个有意义的ToString函数
下一篇: 如何使用RC4进行数据加减密
Knight94
博客等级 码龄25年 1013粉丝 87原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值