C#高级编程9-第3章 对象与类型
- 类与结构
- 类和结构都是对象的模板
- 类定义了处理和访问数据的方法,通过类的实例化进行逻辑处理
- 类与结构的区别是类是引用类型,存储在托管堆上;结构是值类型,存储在栈上的;
类使用class进行修饰,结构使用struct修饰,类的实例通过关键字new进行声明
class PhoneCustomer
{
public const string DayOfSendingBill="Monday";
public int CustomerID; public void Get()
{ }
} struct PhoneCustomerStruct
{
public const string DayOfSendingBill="Monday";
} PhoneCustomer pCustomer=new PhoneCustomer();
pCustomer.Get();
- 类
- 数据成员
- 类中的数据和函数都是类的成员,类可以嵌套即类中包含类.
- 类的成员使用访问修饰符修饰。访问修饰符有public、protected、internal protected、private、internal
- public公开的可访问的
- protected派生类可以访问
- internal protected同一命名空间下派生类可以访问
- private私有的,本身类中才可以访问
- internal同一命名空间下可以访问
- 类的数据成员包含类的数据——字段、常量和事件的成员,成员可以是静态数据,静态成员使用static关键字进行声明,常量是经常使用的变量,使用const修饰
- 函数成员
- 方法
- 函数成员包含方法、类或结构、索引器、运算符、构造函数、析构函数
- 方法声明
- 方法由访问修饰符、返回值类型、方法名、输入参数列表和方法体组成
- 参数列表由参数类型(数据类型)和参数名(方法体引用名)组成。方法由返回值,则通过return关键字返回结果,如果没有返回值指定返回类型为void
public string Add(string name)
{
return "我的名字是:"+name;
} public void Add(string name)
{
Console.Write("我的名字是:"+name);
}
- 方法调用
- 方法通过对象的实例进行调用,使用static修饰的方法使用类名进行调用.
- 参数传递
- 参数通过引用或值传递给方法
- 在变量通过引用传递给方法时,被调用的方法得到的是这个变量即内存中变量的指针。
- 所以在方法内部对变量进行的修改在方法退出后仍旧有效。
- 如果变量通过值传递给方法,被调用的方法得到的变量是一个复制副本,方法退出后,对变量的修改会丢失。
- 对于复杂的数据类型,按引用传递的效率更高,因为值传递时,需要复杂大量数据。
- 参数通过引用或值传递给方法
- ref参数
- 使用ref关键字传递方法参数时,必须给传递给方法的参数进行初始化。
- 使用ref关键字传递值变量时,迫使值传递通过引用传送给方法。
- out参数
- 使用out关键字传递方法参数,必须给传递给方法的参数进行初始化。
- out参数一般用来输出多个返回值。因为return只能返回一个值。
- 对于现在的C#而言,out参数用法已经很少了,可以使用tuple类进行使用。
- 命名参数
- 调用方法时,指定方法参数名和参数值,这样可以不按照顺序去传值。坏处是,调用方法的代码太长
- 可选参数
- 可选参数一般作为方法的最后一个参数值,作为可选参数。作为可选参数,在定义时必须给予默认值,它和重载方法是有区别的,
- 重载方法是不同方法,而可选参数弥补了这一缺失,给定一个方法可选参数指定。
public deciimal Add(int num,decimal price=)
{
return num*price;
} 调用
Add()或者Add(,)
- 方法重载
- 不同方法,方法名相同方法参数不同。
- 方法参数不同表现在参数类型不同、参数数量不同
- 属性
- 属性表现为一个方法或一对方法,和字段不同的是,它有get和set访问器;属性允许给它定义一个私有字段,get和set访问器对私有字段进行了读写操作。
- 私有字段的命名可以以“_”开头,但是必须小写开头。
- get访问器提供了返回属性声明的类型值;
- set访问器需要指定值,编译器给定假设值value.
- 只读只写属性
- 只读属性是因为只设置了get访问器,没有set访问器,使属性不可修改。一般情况有set访问器不是必须定义的。
- 属性的访问修饰符
- C#允许给属性get和set访问器定义修饰符,属性因此可以具备公有的get访器和受保护的set访器
- 自动属性
- 即直接声明属性,不用定义get和set访器的行为方式。也不用定义私有字段。编译器会自动创建。但是自动属性不能验证值的有效性。
- 构造函数
- 类的实例化函数,构造函数就是声明一个方法名与类名相同,但是没有返回类型,构造函数还允许重载。在默认情况下编译器提供了默认的构造函数。构造函数是没有参数的。但是一旦定义了有参数的构造函数,编译器则不提供默认的构造函数。构造函数参数名允许和类的属性名相同,但是调用时允许使用关键字this进行指定。
- 静态构造函数
- 静态构造函数顾名思义,函数名和类名相同,且必须是静态static的,一个类只能有一个静态构造函数。且不能有访问修饰符。因为这个函数仅仅用于初始化,不能调用和外部传参。因此函数也不存在参数。函数在类调用之前,.NET运行库就讲其进行初始化。同时因为是静态的,所以函数体内不能使用实例成员属性。只能使用静态成员。
- 构造函数中调用构造函数
- 一个类中可以有多个构造函数,使用this关键字调用类中其他的构造函数,如果需要调用基类的构造函数可以使用base关键字
- 只读字段
- 使用readonly进行修饰。与常量不同的是,常量需要给定初始值,而readonly则不需要在定义时指定。一旦指定值之后,不能对值进行修改。这会在运行时进行判断。
- 方法
- 匿名类型
- var关键字,用于表示隐式类型的变量,var与new关键字同时使用,才能创建匿名类型
- 匿名类型是一个继承Object类,没有名称的类型,通过初始化器判断类型的属性,因此该类型必须初始化定义类型行为和属性。
- 匿名类型中的属性允许是匿名类型,一般情况下匿名类型实例化后的对象属性是只读的。但是如果匿名类型定义的属性,其属性值是对象引用类型。则是可以修改的。
属性嵌套
var captain=new
{
FirstName = new {
name="admin",
age=
} }
引用类型可写属性
var doctor=new
{
Items=new List<int>(),
Captain=captain
}另外提一点,匿名类型实例对象的ToString()方法可以将匿名类型转换为json对象字符串。至于匿名方法则和委托离不开,后续会说明。
- 结构
- 结构是值类型,数据接口比类小。
- 结构是不能被继承的,并且编译器会给定默认的无参构造方法,我们不能定义无参构造方法。
- 使用结构,可以指定字段在内存中的布局
- 类与结构的区别
- 结构是值类型,不用new实例,只要定义就能使用属性进行设置属性值。但是不能使用没有初始化的属性作为值传递。否则会发生异常。
- 正常的代码:
-
异常的代码
-
结构在分配内存时速度快,不需要等待垃圾回收,只是作为方法参数传递时,因为是值类型,传递的是结构的复制品,方法体内修改后会丢失。因此需要加上ref关键字进行传递。
- 结构和继承
- 结构不能被继承,但是结构继承了Object类,因此拥有了Object类的行为
- 结构的构造函数,因为结构的构造函数定义了默认构造函数,所以结构中定义的字段不能直接赋值。因为默认构造函数会给这些字段赋初始值,如果是数值则默认赋值0,如果是对象默认赋null
- 数据成员
- 弱引用
在应用程序代码内实例化一个类或结构时,只要有代码引用,就会形成强引用。这意味着垃圾清理器在其类或结构的使用范围中有引用它的地方都不会清理内存。一般而言是好事,但是对于大数据量且不经常访问的对象进行强引用时,占用内存巨大。此时可以使用弱引用。
弱引用:由WeakReference类创建的。该对象可能任何时刻被回收。所以引用该对象时,需要确认对象数据是否存在。
创建对象时,实例化WeakReference类对象,作为初始化构造器,将被创建的对象作为WeakReference类构造方法参数进行初始化。在调用时使用WeakReference实例对象的IsAlive属性判断是否存在数据。存在则说明可以调用该对象。通过WeakReference实例对象的Target属性获得该对象。但是因为Target属性的数据类型是Object类型,因此在获取对象时需要使用as关键字进行强制转换。
- 部分类
partial关键字可以将一个类、结构、方法、接口放在多个文件中。一般情况下,一个类会有很多方法和属性,因为某些属性和方法需要分离开来,比如类的一部分成员是设计部分。一部分成员是业务逻辑部分,这时候需要拆分为2个文件方便维护和开发。还有时候因为类的一部分成员是供其他功能调用的。一部分成员作为单个功能使用的。也可以拆分出来。编译时,编译器会将partial标识的多个文件同属于一个类里面的成员、特性、XML描述、接口、泛型进行合并在一起。
例2
不过需要注意的是,如果声明类中使用了下面的关键字,那么多个文件的同一个分部类的这些关键字标识要保持一致。
- 静态类
静态类在类的声明class前加上static修饰。当然类都是静态的了,那么属性和方法都必须是静态的,调用静态成员时直接使用类名进行调用即可。因为是静态的.NET运行库在调用时便已经进行了初始化。所以通过类型调用即可。
- Object类
所有.NET类都派生自Object类,对于结构,这个派生是间接的,结构是派生自ValueType值类型,值类型派生自Object类。
Object类公开方法
ToString方法获取对象的字符串,或者进行格式化,或者转为json格式,允许被重写。
GetHashCode方法,如果对象放在名为映射(散列表或字典)的数据结构中,就可以使用该方法。当类作为字典的一个键时,需要重写该方法。
Equals方法,比较对象是否相等的方法,在.NET FrameWork中比较相等是有相当复杂的模式的。
Finalize方法,在Object类中没有什么行为。在引用对象作为垃圾被回收以清理资源时调用它。如果对象有对未托管资源的引用。可以重写该方法。
GetType方法,返回类的实例,这个对象实例提供对象成员所属类的很多信息
MemberwiseClone方法,只复制对象,返回对副本的一个引用。得到的副本是一个浅表复制,即它复制了类中所以值类型,如果类包含内嵌引用,只复制引用,不复制对象。
- 扩展方法
扩展方法它表现在静态类的静态方法中,如果一个封装的代码类不能进行修改。但是需要给它添加方法则需要使用到扩展方法。
扩展方法在静态方法中,方法参数的第一个参数使用this修饰,第一个参数类型即被扩展的类类型,在方法体内,通过第一个参数类型的实例对象访问对象的成员。不过只能访问该对象的所以公共成员。如果扩展方法的参数与已有类型的方法冲突,可能会造成方法被替换的问题。
扩展方法在调用时,直接是被扩展类的实例调用此扩展方法即可。
C#高级编程9-第3章 对象与类型的更多相关文章
- c#高级编程第七版 学习笔记 第三章 对象和类型
第三章 对象和类型 本章的内容: 类和结构的区别 类成员 按值和按引用传送参数 方法重载 构造函数和静态构造函数 只读字段 部分类 静态类 Object类,其他类型都从该类派生而来 3.1 类和结构 ...
- 读《C#高级编程》第1章问题
读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...
- C#高级编程9 第16章 错误和异常
C#高级编程9 第16章 错误和异常 了解这章可以学会如何处理系统异常以及错误信息. System.Exception类是.NET运行库抛出的异常,可以继承它定义自己的异常类. try块代码包含的代码 ...
- C#高级编程9 第18章 部署
C#高级编程9 第18章 部署 使用 XCopy 进行部署 本主题演示如何通过将应用程序文件从一台计算机复制到另一台计算机来部署应用程序. 1.将项目中生成的程序集复制到目标计算机,生成的程序集位于项 ...
- C#高级编程9 第17章 使用VS2013-C#特性
C#高级编程9 第17章 使用VS2013 编辑定位到 如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中. 可以设置项目并行生成数 版本控制软件设置 所有文本编辑器行号显示 ...
- 【读书笔记】C#高级编程 第三章 对象和类型
(一)类和结构 类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法. 类和结构的区别:内存中的存储方式.访问方式(类是存储在堆上的引用类型,结构是存储在栈的值类型)和它 ...
- C#高级编程笔记之第二章:核心C#
变量的初始化和作用域 C#的预定义数据类型 流控制 枚举 名称空间 预处理命令 C#编程的推荐规则和约定 变量的初始化和作用域 初始化 C#有两个方法可以一确保变量在使用前进行了初始化: 变量是字段, ...
- C#高级编程9 第14章 内存管理和指针
C#高级编程9 内存管理和指针 后台内存管理 1) 值数据类型 在处理器的虚拟内存中有一个区域,称为栈,栈存储变量的浅副本数据,通过进入变量的作用域划分区域,通过离开变量的作用域释放. 栈的指针指向栈 ...
- Java多线程编程核心技术-第2章-对象及变量的并发访问-读书笔记
第 2 章 对象及变量的并发访问 本章主要内容 synchronized 对象监视器为 Object 时的使用. synchronized 对象监视器为 Class 时的使用. 非线程安全是如何出现的 ...
- Java编程思想(第一章 对象入门)总结
面向对象编程(oop) 1.1抽象的进步 所有编程语言的最终目的都是提供一种“抽象”方法. 难点是 在机器模型(位于“方案空间”)和实际解决问题模型(位于“问题空间”)之间,程序员必须建立起一种联 ...
随机推荐
- C#基础之静态和非静态的区别
1.在非静态即可有非静态成员又可以有静态成员 2非静态调用创建类的对象.方法名,静态成员直接引用对象名
- SQL 根据关联表更新主表中字段数据
今天遇到一个客户的数据更新问题,两个相关联的表,一个主表用于保存单据主要信息,一个副表用于保存单据的明细信息:现在要把主表的其中一个字段的数据更新到副表的一个字段中保存.精通的SQL语法的,当然是很简 ...
- Hadoop(三):MapReduce程序(python)
使用python语言进行MapReduce程序开发主要分为两个步骤,一是编写程序,二是用Hadoop Streaming命令提交任务. 还是以词频统计为例 一.程序开发1.Mapper for lin ...
- hihocoder1636 Pangu and Stones(区间DP(石子合并变形))
题目链接:http://hihocoder.com/problemset/problem/1636 题目大意:有n堆石头,每次只能合并l~r堆,每次合并的花费是要合并的石子的重量,问你合并n堆石子的最 ...
- 域名解析A记录与CNAME有什么区别?
A记录是直接将域名指向某个IP,如果您的主机IP不常变动就建议使用A记录.而别名解析是先将域名解析到主机别名再转跳到IP这样主机IP改变了不用重新解析.如果主机IP常变建议用别名解析 A记录正规些.独 ...
- overlay实现容器跨主机通信
本节内容: Docker容器跨主机通信方案 环境信息 升级内核 安装docker 防火墙设置和开启内核转发 安装启动consul 启动Docker 创建overlay network 创建容器 测试容 ...
- 30 最小的k个数
输入n个整数,找出其最小的k个数,例如输入4,5,1,6,2,7,3,8,最小的4个数为1,2,3,4 解法一:快排思想,会改变原数组 O(n) 注意是vector<int>& ...
- 【PAT】1016 部分A+B(15 分)
1016 部分A+B(15 分) 正整数 A 的“DA(为 1 位整数)部分”定义为由 A 中所有 DA 组成的新整数 PA.例如:给定 A=3862767,DA=6,则 A ...
- day9作业
题目:简单主机批量管理工具 需求: 1.主机分组: 2.登录后显示主机分组,选择分组后查看主机列表: 3.可批量执行命令.发送文件,结果实时返回: 4.主机用户名密码可以不同.
- 易普优高级计划排程Light版助力中小企业实现精益化计划
易普优高级计划排程Light版助力中小企业实现精益化计划 一.业务与排产需求 根据统计,目前中小企业已经占到我国工业企业总数的95%以上,对中国GDP贡献超过60%,税收超过了50%,提供了70%的进 ...