02010703 深入理解类03-this关键字、索引器、分部类和分布类型
02010703 深入理解类03-this关键字、索引器、分部类和分布类型
1. this关键字
- this关键字在类中使用, 是对当前实例的引用,它只能被用在下列类成员的代码中。
- 实例构造函数。
- 实例方法。
- 属性和索引器的实例访问器。
- this关键字使用注意事项:因为静态成员不是实例的一部分,所以不在任何静态函数成员的代码中使用this关键字。
- this关键字用于如下目的。
- 用于区分类的成员,局部变量或参数。
- 用作调用方法的实参。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo01
{
class MyClass
{
int Val = 10;
public int ReturnMaxNum(int Val)
{
return Val > this.Val ? Val : this.Val;
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
Console.WriteLine($"{mc.ReturnMaxNum(5)}");
Console.WriteLine($"{mc.ReturnMaxNum(20)}");
Console.ReadLine();
}
}
}
控制台输出:
10
20
说明:
1. 字段和形参的名称相同都是Val,在方法内使用this关键字引用字段。
2. 此命名冲突仅用于演示的目的,我们在开发中不应对成员变量和参数使用相同的名称。
3. 虽然理解this关键字的用途和功能很重要,但它在实际上很少使用。
2. 索引器
2.1 什么是索引器
- 索引器是一组get和set访问器,与属性类似。
// 索引器的表现形式
string this [int index]
{
set
{
...
}
get
{
...
}
}
2.2 索引器和属性
- 索引器和属性在很多方面类似
- 和属性一样,索引器不用分配内存来存储。
- 索引器和属性都主要被用来访问其它数据成员,它们与这些成员关联,并为它们提供获取和设置访问。
- 属性通常表示单个数据成员。
- 索引器通常表示多个数据成员。
- 关于索引器,一些注意事项如下。
- 和属性一样,索引器可以只有一个访问器,也可以两个两个都有。
- 索引器总是实例成员,因此不能被声明为static。
- 和属性一样,实现get和set访问器的代码不一定关联到某个字段或属性。索引器这段代码可以做任何事情,也可以什么都不做。只要get访问器能索引器指定类型的值即可。
3.3 声明索引器
关键字 参数列表
↓ ↓
ReturnType this [Type param1, ...]
{
get
{
...
}
set
{
...
}
}
说明:
1. 索引器没有名称。在名称位置时关键字this来表示实例的引用。
2. 参数列表在[]中间。
3. 参数列表中必须至少声明一个参数。
3.4 索引器的set访问器
- 当索引器被用于赋值时,set访问器被调用,并接受两项数据。
- 一个名为value的隐式参数,其中持有要保存的数据。
- 一个或更多个索引参数,表示数据应该保存在哪里。
- set访问器的语法和含义
// set访问器的语法
ReturnType this [ParamList]
{
get
{
...
}
set
{
...
}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// set访问器的含义
隐式参数
↓
void set(ParamList, Type value)
{
...
}
说明:
1. set访问器它的返回类型为void。
2. set访问器它使用的参数列表和索引器声明中的相同。
3. set访问器有一个名为value的隐式参数,值类型和索引器类型相同。
3.5 索引器的get访问器
- 当使用索引器获取值时,可以通过一个或多个索引参数调用get访问器。索引参数指示获取哪个值。
- get访问器的语法和含义
// get访问器的语法
ReturnType this [ParamList]
{
get
{
...
}
set
{
...
}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// get访问器的含义
隐式参数
↓
Type get(ParamList)
{
...
return ValueOfType;
}
说明:
1. get访问器的参数列表和索引器声明中相同。
2. get访问器返回与索引器类型相同的值。
3.6 关于索引器注意事项
- 和属性一样,不能显式调用get和set访问器。
- 当索引器用在表达式中获取值时,将自动调用get访问器。
- 当使用赋值语句对索引器赋值时,将自动调用set访问器。
- 在“调用”索引器时,要在[]中提供参数。
emp[0] = "Doe"; // 调用set访问器
string MyName = emp[0]; // 调用get访问器
3.7 索引器示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo01
{
class MyClass
{
int MyVal01;
int MyVal02;
public int this [int index]
{
get
{
return (0 == index) ? MyVal01 : MyVal02;
}
set
{
if (0 == index)
MyVal01 = value;
else
MyVal02 = value;
}
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
Console.WriteLine($"MyVal01={mc[0]},MyVal02={mc[1]}");
mc[0] = 10;
mc[1] = 20;
Console.WriteLine($"MyVal01={mc[0]},MyVal02={mc[1]}");
Console.ReadLine();
}
}
}
控制台输出:
MyVal01=0,MyVal02=0
MyVal01=10,MyVal02=20
3.8 索引器重载
- 只要索引器的参数列表不同,类就可以有任意多个索引器。只有索引器类型不够的,这叫做索引器重载。
- 索引器重载必须都有相同的“名称”,即this访问引用。
4. 访问器的访问修饰符
- 可以为两个访问器分配不同的访问级别。将set访问器声明为private,将get访问器声明为public。
- 这样设定访问修饰符,可以从类的外部读取属性,但只能在类的内部设置属性,这是一个非常重要的封装工具。
- 如果一个属性的访问修饰符是public,那么可以在较低的4个访问级别中,可以把任意一个级别给它的访问器。但如果属性的访问级别是protected,则唯一能对访问器使用的访问修饰符是private。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo01
{
class MyClass
{
public string Name { get; private set; } // 设定不同级别的访问器
public MyClass(string name)
{
Name = name;
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass("Qinway");
Console.WriteLine($"Person's name is {mc.Name}.");
Console.ReadLine();
}
}
}
控制台输出:
Person's name is Qinway.
说明:
1. 仅当成员(属性或索引器)既有get访问器同时也有set访问器时,其访问器才能有访问修饰符。
2. 虽然get和set两个访问器必须同时出现才能有访问修饰符,但是只能有一个访问器有访问修饰符。
3. 访问器的访问修饰符的限制,必须比成员的访问级别更严格。
5. 分部类和分布类型
5.1 分部类
- 类的声明可以分割成几个分布类的声明。
- 每个分部类的声明都含有一些类成员的声明。
- 类的分部类声明可以在同一个文件,也可以在不同文件中。
- 每个分部类声明必须标注为partial class,而不是单独的关键字class。
// 分部类看起来和普通类声明相同,只是增加了类型修饰符partial。
partial class MyClass // 分部类1
{
...
}
partial class MyClass // 分部类2
{
...
}
说明:
1. 分部类的名称要相同。
2. partial是类型修饰符而不是关键字,所以在其它上下文中,可以用它作为标识符。但是partial直接用在关键字class,struct或interface之前时,它表示分部类型。
5.2 分部类注意事项
- 组成类的所有分部类声明虽然可以在不同的文件中,但所有的分部类声明都必须在一起编译。此外,使用分部类声明的类必须有相同的含义,就好像所有类成员都声明在一个单独的类声明体内部。
6. 分部方法
6.1 分部方法简介
- 分部方法是声明在分部类中不同部分的方法。分部方法的不同部分可以声明在分部类的不同部分中,也可以声明在同一部分中。
- 分部方法的两个部分如下。
- 定义分布方法声明。
- 给出签名和返回类型。
- 声明的实现部分只是一个分号。
- 实现部分方法声明。
- 给出签名和返回类型。
- 以普通的语句块形式实现。
- 定义分布方法声明。
6.2 分部方法的重点
- 分部方法的定义声明和实现声明的签名和返回类型必须匹配,签名和返回类型具有如下特征。
- 返回类型必须是void。
- 签名不能包括访问修饰符,这使得分布方法是隐式私有的。
- 参数列表不能包括out参数。
- 在定义声明和实现声明中都必须包含上下文关键字partial,并且直接放在关键字void之前。
- 分部方法可以有定义部分而没有实现部分(这种情况下,编译器把方法的声明以及方法内部任何对方法的调用都被移除),但是不能只有分布方法的实现部分而没有定义部分。
7. 分部类和分布方法示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo01
{
partial class MyClass // 定义分部类
{
partial void MyFunc(int x, int y); // 定义分布方法,必须是void修饰。
public void Add(int x, int y)
{
MyFunc(x, y);
}
}
partial class MyClass // 定义分部类
{
partial void MyFunc(int x, int y) // 实现分布方法,必须是void修饰。
{
Console.WriteLine($"Sum is {x + y}.");
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
mc.Add(10, 20);
Console.ReadLine();
}
}
}
控制台输出:
Sum is 30.
说明:
1. 分部方法是隐式私有的,所以MyFunc不能从类的外部调用。方法Add是调用MyFunc的公有方法。
2. 创建一个MyClass对象mc,mc调用公有方法Add,Add方法调用方法MyFunc。
结尾
书籍:C#图解教程
著:【美】丹尼尔 · 索利斯;卡尔 · 施罗坦博尔
译:窦衍森;姚琪琳
ISBN:978-7-115-51918-4
版次:第5版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

浙公网安备 33010602011771号