C#基础知识整理:基础知识(11) 值类型,引用类型
发布日期:2021-11-07 06:40:50 浏览次数:5 分类:技术文章

本文共 5872 字,大约阅读时间需要 19 分钟。

C#是面向对象的语言,在面向对象的思想中,只有对象,所有事物都可以用类描述。所以比如这些,int,bool,char,string,double,long等都是类,那么像,30,2.5,"test"都是对应类的一个对象。

static void Main(string[] args)        {            string istring = 30.ToString();            string dstring = 2.5.ToString();            string sstring = "test".ToString();            Console.WriteLine(string.Format("{0},{1},{2}", istring, dstring, sstring));            Console.ReadLine();        }

输出:

 可以看出它们有ToString()这个方法,所以它们是对象。

 在平时写代码时,定义数据类型除了上述的这种之外,肯定都用过:

static void Main(string[] args)        {            Int32 i = 0;            UInt32 j = 0;            String str = "test";            Console.ReadLine();        }

    这个其实是.NET的一个机制,.NET是一个平台,这个平台上有C#,VB这些语言。因此,.NET定义了一系列类型,映射到不同的语言中,Int32在c#中就是int。这样的数据类型称作基元类型,在C#中类的对象必须使用new生成。而这一部分类直接就可以用常量表示。基元类型定义在.net Framework中,System命名空间下。看一下基元类型在C#语言中的类型映射。

.NET Framework基元类型

C#类型

取值范围 备注

System.Boolean

bool

true/false /
System.Byte byte 0 ~255

无符号8位整数

System.Sbyte sbyte -128 ~ 127 有符号8位整数
System.Char char 0 ~ 65,535 无符号16位整数
System.Int16 short

-32,768 ~ 32,767

有符号16位整数
System.UInt16 ushort 0 ~ 65,535 无符号16位整数
System.Int32 int -2,147,483,648 ~ 2,147,483,647 有符号32位整数
System.Int64 long

-9,223,372,036,854,775,808 ~

9,223,372,036,854,775,807

有符号64位整数
System.UInt64 ulong

0 ~ 18,446,744,073,709,551,615

无符号64位整数
System.Single float

±1.5 × 10-45 ~ ±3.4 × 1038

(7位有效数字)

32位单精度浮点数
System.Double double

±5.0 × 10-324 到 ±1.7 × 10308

(15至16位有效数字)

64位双精度浮点
System.Decimal decimal

±1.0 × 10-28 到 ±7.9 × 1028

(27至28位有效数字)

128位浮点数数
System.String string 任意字符串 /
System.UInt32 uint 0 ~ 4,294,967,295 无符号32位整数

表中的除了string是引用类型(后面单独解释),其它都是值类型。

下面简单介绍下引用类型和值类型。
学习C语言的时候有个堆和栈的概念。
堆区——程序员分配释放,或者程序结束有OS回收,分配方式类似于链表。
栈区——由编译器自动分配释放,存放函数的参数值,变量值等。
栈内存结构可以快速的分配内存和回收内存,但栈空间有限,过多使用会“溢出”,因此栈只分配常用的,占用空间小的数据类型;堆内存结构分配内存较慢,但是利用空间大,可以存放大型数据。
在C#中,基本上所有的数据都存储在“堆”结构中,称之为“托管堆”,受.NET垃圾回收监控。但是相对于栈堆结构中内存分配效率比较低。为了正确进行垃圾回收,每次分配的堆空间比实际所需空间稍大,小型数据使用堆是不太合适的。
可以比较看一下值类型和引用类型:
C#中提供了Struct定义值类型,直接在栈上分配内存。

///     /// 使用struct定义一个值类型,    /// 值类型的只能实现接口,不能继承类    ///     public struct StructPositiveNumber : ICloneable      {        ///         /// 值类型字段        ///         private int number;        ///         /// 静态只读字段,作为类的初始值        ///         public readonly static StructPositiveNumber InitialValue = new StructPositiveNumber();        ///         /// 属性        ///         public int Number        {            get            {                return number;            }            set            {                if (value <= 0)                {                    throw new Exception();                }                this.number = value;            }        }        ///         /// 可以定义构造器,但是和类不同,这里的默认构造器依然存在        ///         public StructPositiveNumber(int value)        {            if (value <= 0)            {                throw new Exception();            }            this.number = value;        }        ///         /// 实现克隆方法,返回当前对象        ///         /// 
public object Clone() { return new StructPositiveNumber(this.number); } }

调用

static void Main(string[] args)        {            //声明变量,赋值            StructPositiveNumber pNumber1 = StructPositiveNumber.InitialValue;            pNumber1.Number = 1;            //pNumber1赋给pNumber2            StructPositiveNumber pNumber2 = pNumber1;            //改变pNumber2的值            pNumber2.Number = 2;            //看打印结果,改变了pNumber2的值,但是不影响pNumber1            Console.WriteLine(pNumber1.Number);//1            Console.WriteLine(pNumber2.Number);//2            //重新初始化pNumber2,通过构造器生成改变了初始值。            pNumber2 = new StructPositiveNumber(3);            Console.WriteLine(pNumber2.Number);//3            //调用Clone将pNumber2复制给pNumber1            pNumber1 = (StructPositiveNumber)pNumber2.Clone();            Console.WriteLine(pNumber1.Number);//3            //改变pNumber1的值,但是pNumber2值不改变            pNumber1.Number = 4;            Console.WriteLine(pNumber1.Number);//4            Console.WriteLine(pNumber2.Number);//3            Console.ReadLine();        }

结果

再看引用类型定义的:

public class ClassPositiveNumber : ICloneable    {        private int number;        public int Number        {            get            {                return this.number;            }            set            {                if (value <= 0)                {                    throw new Exception();                }                this.number = value;            }        }        //引用类型自己可以初始化为null,无需定义初始值        //public readonly static ClassPositiveNumber InitialValue = new ClassPositiveNumber();        public ClassPositiveNumber(int value)        {            if (value <= 0)            {                throw new Exception();            }            this.number = value;        }        public object Clone()        {            return new ClassPositiveNumber(this.number);        }    }

调用

static void Main(string[] args)        {            ClassPositiveNumber cNumber1;//默认值为null            cNumber1 = new ClassPositiveNumber(1);            ClassPositiveNumber cNumber2 = cNumber1;            cNumber2.Number = 2;            //可以看出,两个引用引用到了相同的对象            Console.WriteLine(cNumber1.Number);//2            Console.WriteLine(cNumber2.Number);//2            //重新初始化cNumber2,之前的对象已被丢弃            cNumber2 = new ClassPositiveNumber(3);            Console.WriteLine(cNumber2.Number);//3                        //复制是复制一个对象的副本,因此,是两个不同的对象            cNumber1 = (ClassPositiveNumber)cNumber2.Clone();            Console.WriteLine(cNumber1.Number);//3            cNumber1.Number = 4;            Console.WriteLine(cNumber1.Number);//4            Console.WriteLine(cNumber2.Number);//3            Console.ReadLine();        }

结果

通过例子,可以看出值类型的特点如下:

a、使用struct声明;
b、不能继承类,但是可以实现接口(当然除object类外);
c、值类型使用值类型做为字段,但是字段无法有默认值;
c、值类型中必须有默认构造器,而且自己定义构造器后,默认的无参数的构造器依然存在。而且在构造其中只能访问类中的字段,但是不能访问属性。符号=对于值类型来说是赋值,所以赋值是值类型变量不能为空,因为值类型没有引用的概念,肯定有值。

代码下载:

转载地址:https://blog.csdn.net/yysyangyangyangshan/article/details/7784542 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C#基础知识整理:基础知识(12) 超类Object
下一篇:C#中List的Find方法的使用

发表评论

最新留言

不错!
[***.144.177.141]2024年04月04日 20时17分48秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

更精细的分支保护策略,如何实现? 2019-04-26
Gitee 企业版更新:新视图 & 新模块 2019-04-26
是时候拥抱内源了 2019-04-26
不用引入JQuery,前端开发们一行代码就能使用的提示信息开源组件 2019-04-26
[Leetcode 每日精选](本周主题-股票) 714. 买卖股票的最佳时机含手续费 2019-04-26
[Leetcode 每日精选](本周主题-股票) 123. 买卖股票的最佳时机 III 2019-04-26
[Leetcode 每日精选](本周主题-股票) 188. 买卖股票的最佳时机 IV 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 990. 等式方程的可满足性 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 面试题 17.07. 婴儿名字 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 721. 账户合并 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 399. 除法求值 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 959. 由斜杠划分区域 2019-04-26
[Leetcode 每日精选](本周主题-并查集) 130. 被围绕的区域 2019-04-26
[leetcode 剑指offer系列] 面试题04. 二维数组中的查找 2019-04-26
[leetcode 剑指offer系列] 面试题05. 替换空格 2019-04-26
[leetcode 剑指offer系列] 面试题06. 从尾到头打印链表 2019-04-26
剑指 Offer 07. 重建二叉树 - leetcode 剑指offer系列 2019-04-26
剑指 Offer 09. 用两个栈实现队列 - leetcode 剑指offer系列 2019-04-26
剑指 Offer 10- I. 斐波那契数列 - leetcode 剑指offer系列 2019-04-26