第 17 节 字段、属性、索引器、常量

第17节 字段、属性、索引器、常量

类的成员

字段

  1. 什么是字段
    1)字段(field)是一种表示与对象或类型(类与结构体)关联的变量(为对象或类型存储数据)
    2)字段是类型的成员,旧称“成员变量”
    3)与对象关联的字段亦称“实例字段”
    4)与类型关联的字段称为“静态字段”,由static修饰

  2. 字段的声明
    1)参见C#语言定义文档
    2)尽管字段声明带有分号,但它不是语句
    3)字段的名字一定是名词

  3. 字段的初始值
    1)无显式初始化时,字段获得其类型的默认值,所以字段“永远都不会未被初始化”
    2)实例字段初始化的时机——对象创建时
    3)静态字段初始化的时机——类型被加载(load)时

  4. 只读字段
    为实例或类型保存一旦初始化之后就不希望再改变的值。
    1)实例只读字段:只有一次赋值的机会,在其构造器或者声明的时候进行里初始化。
    2)静态只读字段:只能在静态构造器里或者在声明的时候初始化。

举例:
实例只读字段:

class Program
{
    static void Main(string[] args)
    {
        Student student = new Student(1);
        Console.WriteLine(student.ID);
    }
}

class Student
{
    public readonly int ID;  //实例只读字段
    public int Age;
    public int Score;

    public static int AverageAge;
    public static int AverageScore;
    public static int Amount = 100;

    public Student(int id)  //在构造器里面初始化,并且之后不能进行修改
    {
        this.ID = id;
    }
}

静态只读字段

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Brush.DefaultColor.Red);
    }
}

struct Color
{
    public int Red;
    public int Green;
    public int Blue;
}

class Brush
{
    public static readonly Color DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };  //静态只读字段
}

静态构造器

class Brush
{
    public static readonly Color DefaultColor;
    static Brush() //静态构造器是static,而实例构造器是public
    {
        Brush.DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };
    }
}

属性(C#所特有的)

什么是属性

  1. 属性(property)是一种用于访问对象或类型的特征的成员,特征反映了状态
  2. 属性是字段的自然扩展
    1)从命名上看,field更偏向于实例对象在内存中的布局,property更偏向于反应现实世界对象的特征
    2)对外:暴露数据,数据可以是存储在字段里的,也可以是动态计算出来的
    3)对内:保护字段不被非法值“污染”
  3. 属性由Get/Set方法对进化而来
  4. 又一个“语法糖”——属性背后的秘密

Get/Set方法

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Student stu1 = new Student();
            stu1.SetAge(20);
            Student stu2 = new Student();
            stu2.SetAge(20);
            Student stu3 = new Student();
            stu3.SetAge(20);

            int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge()) / 3;
            Console.WriteLine(avgAge);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

class Student
{
    private int age; //字段,private 变量命名全用小写字母

    public int GetAge() //GetAge() 方法
    {
        return this.age;
    }

    public void SetAge(int value) //SetAge() 方法
    {
        if (value >= 0 && value <= 120)
        {
            this.age = value;
        }
        else
        {
            throw new Exception("Age value has error!");

        }
    }
}

属性

class Program
{
	static void Main(string[] args)
	{
		try
		{
			Student stu1 = new Student();
			stu1.Age = 20;
			Student stu2 = new Student();
			stu2.Age = 20;
			Student stu3 = new Student();
			stu3.Age = 20;

			int avgAge = (stu1.Age+stu2.Age+stu3.Age)/3;
			Console.WriteLine(avgAge);
		}
		catch(Exception ex)
		{
			Console.WriteLine(ex.Message);
		}
	} 
}

class Student
{
	private int age; //Student类的字段
	public int Age  //Student类的属性
	{
		get
		{
			return this.age;
		}

		set
		{
			if(value>=0 && value<=120) //value是上下文关键字
			{
				this.age = value;
			}
			else
			{
				throw new Exception("Age value has error!");
			}
		}
	}
}

属性的声明

  1. 完整声明——后台(back)成员变量与访问器(注意使用code snippet 和 refactor 工具
    代码提示:propfull + 连续两下tab键(获得代码的框架)。

  2. 简略声明——只有访问器(查看IL代码)
    功能与公有的字段一样,不受保护!!为了传递数据使用
    代码提示:prop + 连续两下tab键(获得代码的框架)。

快速声明属性的三种方法:
1)完整声明:propfull + 连续两下tab键;
2)简略声明:prop + 连续两下tab键
3)高级版本的vs中才有:private int age;将光标放置在 age 字段的中间,点击Ctrl+r、e,应用。

:完整声明与简略声明的最大区别在于getter和setter的不同。

  1. 动态计算值的属性(不懂
  2. 注意实例属性和静态属性
    实例属性:通过数据反应实例当前的状态
    静态属性:通过数据反应类型当前的状态
  3. 属性的名字一定是名词
  4. 只读属性——只有getter没有setter
    1)尽管语法上正确,几乎没有人使用“只写属性”,因为只写属性的主要目的是通过向外暴露数据而表示对象/类型的状态
    2)只读方法:只有 get 没有 set

:如果在 set 方法前面加 private ,则该方法只能在其所属的类里面进行访问,外界不能进行访问,但是该属性不是只读属性

属性与字段的关系

  1. 一般情况下,它们都用于表示实体(对象或类型)的状态
  2. 属性大多数情况下是字段的包装器(wrapper)
  3. 建议:永远使用属性(而不是字段)来暴露数据,即字段永远都是private或protected的

索引器(概述)

什么是索引器
索引器(indexer)是这样一种成员:它是对象能够与数组相同的方式(即使用下标)进行索引。一般用在集合类型!!!

索引器的声明
参见 C# 语言定义文档
声明索引器:
代码提示:index + 连续两下 tab 键

:声明静态索引器

class Program
{
    static void Main(string[] args)
    {
        Student stu = new Student();
        stu["Math"] = 90;
        var mathScore = stu["Math"];
        Console.WriteLine(mathScore.GetType().FullName);
        Console.WriteLine(mathScore);
    }
}

class Student
{
    private Dictionary<string, int> scoreDictionary = new Dictionary<string, int>();

    public int? this[string subject]  //声明索引器,返回值的类型是可空的整型,并用string类型进行索引
    {
        get
        {
            if (this.scoreDictionary.ContainsKey(subject))
            {
                return this.scoreDictionary[subject];
            }
            else
            {
                return null;
            }
        }
        set
        {
            if (value.HasValue == false) //判断可空类型的变量是不是真的有值
            {
                throw new Exception("Score cannot be null");
            }

            if (this.scoreDictionary.ContainsKey(subject))
            {
                this.scoreDictionary[subject] = value.Value; //可空类型的 value.Value 才是它真正的值
            }
            else
            {
                this.scoreDictionary.Add(subject, value.Value);
            }
        }
    }
}

常量

什么是常量

  1. 常量(constant)是表示常量值(即,可以在编译时计算的值)的类成员
  2. 常量隶属于类型而不是对象,即没有“实例常量”
    1)“实例常量”的角色由只读实例字段来担当
  3. 注意区分成员常量与局部常量
    成员常量:类型的成员
    局部常量:用于参与组成方法体中的算法

常量的声明

各种“只读”的应用场景

  1. 为了提高程序可读性和执行效率——常量
  2. 为了防止对象的值被改变——只读字段
  3. 向外暴露不允许修改的数据——只读属性(静态或非静态),功能与常量有一些重叠
  4. 当希望成为常量的值其类型不能被常量声明接受时(类/自定义结构体)——静态只读字段
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值