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※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

posted @ 2025-08-10 22:11  qinway  阅读(10)  评论(0)    收藏  举报