当前位置: 首页 > news >正文

C#语言入门详解(17)字段、属性、索引器、常量

C#语言入门详解(17)字段、属性、索引器、常量

  • 前言
  • 一、字段 Field
  • 二、属性
  • 三、索引器
  • 四、常量


内容来自刘铁猛C#语言入门详解课程。
参考文档:CSharp language specification 5.0 中文版
在这里插入图片描述

前言

类的成员是静态成员 (static member) 或者实例成员 (instance member)。 静态成员属于类, 实例成员属于对象(类的实例) 。下表提供了类所能包含的成员种类的概述。

成员说明
常量与类关联的常量值
字段类的变量
方法类可执行的计算和操作
属性与读写类的命名属性相关联的操作
索引器与以数组方式索引类的实例相关联的操作
事件可由类生成的通知
运算符类所支持的转换和表达式运算符
构造函数初始化类的实例或类本身所需的操作
析构函数在永久丢弃类的实例之前执行的操作
类型类所声明的嵌套类型

本节所讲的字段、属性、索引器、常量为类的四个成员。

一、字段 Field

在这里插入图片描述

  • field原意为田地,在此处意指为数据存放空间。以Student类为例,包含ID、Name两个字段,每个字段为4个字节。则Student的对象占8个字节,这8个字节分为两块田地,分别为ID、Name放不同的数据。

在这里插入图片描述

  • 使用 static 修饰符声明的字段定义静态字段 (static field)。 一个静态字段只标识一个存储位置。无论对一个类创建多少个实例, 它的静态字段永远都只有一个副本,可用来表示类当前的状态,即静态字段的初始化在运行环境加载类时,后面不再初始化。声明静态字段时设置初始化值与在静态构造器里面初始化静态字段其实是一样的。
  • 不使用 static 修饰符声明的字段定义实例字段 (instance field)。 类的每个实例都为该类的所有实例字段创建一个单独副本,每次创建实例都会初始化字段,实例字段的初始化在创建时。声明实例字段时初始化值与在实例构造器里面初识化实例字段是一样的。
  • readonly修饰的字段只有一次赋值机会,可在声明时或构造器中赋值。
class Program
{static void Main(string[] args){var stuList = new List<Student>();for (int i = 0; i < 100; i++){var stu = new Student{Age = 24,Score = i,};stuList.Add(stu);}int totalAge=0;int totalScore=0;foreach (var stu in stuList){totalAge += stu.Age;totalScore += stu.Score;}//调用静态字段,可直接使用 类.字段 的形式Student.AverageAge = totalAge / Student.Amout;Student.AverageScore = totalScore / Student.Amout;Student.ReportAmount();Student.ReportAverageAge();Student.ReportScore();}class Student{//普通字段public readonly int ID;public int Age;public int Score;//静态字段//public、static为修饰符,修饰符在使用中最少使用一个,且必须是有意义的//访问级别 static修饰符 变脸类型 成员名public static int AverageAge;public static int AverageScore;public static int Amout;// readonly修饰的字段只有一次赋值机会public Student(int id){this.ID = id;}public Student(){Amout++;}//静态方法public static void ReportAmount(){Console.WriteLine(Amout);}public static void ReportAverageAge(){Console.WriteLine(AverageAge);}public static void ReportScore(){Console.WriteLine(AverageScore);}}
}

二、属性

在这里插入图片描述

  • 属性为字段的包装器,为避免字段被污染,需要对字段的赋值制定一定的规则,这个规则通过属性来实现。
  • prop + 2 * TAB:属性的简略声明
  • propfull + 2 * TAB:属性的完整声明
  • 使用 Get/Set 方法对之前:
class Program
{static void Main(string[] args){var stu1 = new Student(){Age = 20};var stu2 = new Student(){Age = 20};var stu3 = new Student(){// 非法值,污染字段Age = 200};var avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;Console.WriteLine(avgAge);}
}class Student
{public int Age;
}
  • 在C++/Java等编程语言中演化为 Get/Set 方法:
class Program
{static void Main(string[] args){try{var stu1 = new Student();stu1.SetAge(20);var stu2 = new Student();stu2.SetAge(20);var stu3 = new Student();stu3.SetAge(200);var avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge()) / 3;Console.WriteLine(avgAge);}catch (Exception ex){Console.WriteLine(ex.Message);}}
}class Student
{private int age;public int GetAge(){return age;}public void SetAge(int value){if (value >= 0 && value <= 120){age = value;}else{throw new Exception("Age value has error.");}}
}
  • C++、JAVA 里面是没有属性的,使用 Get/Set 来保护字段的方法至今仍在 C++、JAVA 里面流行。因为 Get/Set 写起来冗长,微软应广大程序员请求,给 C# 引入了属性。
class Program
{static void Main(string[] args){try{var stu1 = new Student();stu1.Age=20;var stu2 = new Student();stu2.Age = 20;var stu3 = new Student();stu3.Age = 200;var avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;Console.WriteLine(avgAge);}catch (Exception ex){Console.WriteLine(ex.Message);}}
}class Student
{private int age;public int Age{get{return age;}set{if (value >= 0 && value <= 120){age = value;}else{throw new Exception("Age value has error.");}}}
}
  • 动态计算值的属性。主动计算,每次获取 CanWork 时都计算,适用于 CanWork 属性使用频率低的情况。
class Program
{static void Main(string[] args){try{var stu1 = new Student();stu1.Age = 12;Console.WriteLine(stu1.CanWork);}catch (Exception ex){Console.WriteLine(ex.Message);}}
}class Student
{private int age;public int Age{get { return age; }set{age = value;}}public bool CanWork{get{return age > 16;}}
}
  • 被动计算,只在 Age 赋值时计算一次,适用于 Age 属性使用频率低,CanWork 使用频率高的情况。
class Program
{static void Main(string[] args){try{var stu1 = new Student();stu1.Age = 12;Console.WriteLine(stu1.CanWork);}catch (Exception ex){Console.WriteLine(ex.Message);}}
}class Student
{private int age;public int Age{get { return age; }set{age = value;CalculateCanWork();}}private bool canWork;public bool CanWork{get { return canWork; }}private void CalculateCanWork(){canWork = age > 16;}
}
  • 建议:永远使用属性(而不是字段)来暴露数据,即字段永远是 private 或 protected 的。 字段只在类内部使用,类之间交换数据,永远只用属性。

三、索引器

在这里插入图片描述

  • indexer + 2 * TAB:快速声明索引器
  • 索引器一般用于集合中,下面示例仅为展示,一般很少用在非集合中。
class Program
{static void Main(string[] args){var stu = new Student();stu["Math"] = 90;stu["Math"] = 100;var mathScore = stu["Math"];Console.WriteLine(mathScore);}
}class Student
{//键值对,string为科目名称,int为socreprivate Dictionary<string, int> scoreDictionary = new Dictionary<string, int>();public int? this[string subject]{get{if (scoreDictionary.ContainsKey(subject)){return scoreDictionary[subject];}else{return null;}}set{if (value.HasValue == false){throw new Exception("Score cannot be null");}if (scoreDictionary.ContainsKey(subject)){//  可空类型的 Value 属性才是其真实值。scoreDictionary[subject] = value.Value;}else{scoreDictionary.Add(subject, value.Value);}}}
}

四、常量

在这里插入图片描述

  • 示例为第四种场景:类不可以用作常量,需使用静态只读字段
class Program
{static void Main[string[] args){Console.WriteLine[WASPEC.WebsiteURL);}
}class WASPEC
{public const string WebsiteURL = "http://www.waspec.org";//类 不能用作常量//public const Building Location = new Building[) { Address = "Some Address” };public static readonly Building Location = new Building("Some Address")
class Building}class Building
{public Building[string address){this.Address = address;}public string Address { get; set; }
}
http://www.dtcms.com/a/359385.html

相关文章:

  • 云计算与服务器
  • 【C#】在一个任意旋转的矩形(由四个顶点定义)内绘制一个内切椭圆
  • 在AlmaLinux或CentOS 8上编译安装ZLMediaKit流媒体服务器
  • Mysql中事务隔离级别有哪些?
  • 【行业洞察】多智能体的风口浪尖--微软MagenticOne/UI
  • android中常见布局及其约束
  • 鸿蒙创新赛活动——Mac提交压缩失败后续
  • [linux仓库]解剖Linux内核:文件描述符(fd)的‘前世今生’与内核数据结构探秘
  • 如何绕过 disable-devtool.js 打开控制台
  • mac Monterey 安装erlang23
  • 【高级】系统架构师 | 信息系统基础
  • Wi-Fi技术——MAC特性
  • Java提供高效后端支撑,Vue呈现直观交互界面,共同打造的MES管理系统,含完整可运行源码,实现生产计划、执行、追溯一站式管理,提升制造执行效率
  • 基于EHO与BP神经网络分类模型的特征选择方法研究(Python实现)
  • 现代C++性能陷阱:std::function的成本、异常处理的真实开销
  • HarmonyOS 应用开发:基于API 12+的现代化实践
  • 第4章从一条记录说起-InnoDB记录结构
  • openssl使用SM2进行数据加密和数据解密
  • Linux中卸载和安装Nginx
  • 第24章学习笔记|用正则表达式解析文本文件(PowerShell 实战)
  • Git版本管理工具零基础学习
  • ThinkPHP8学习篇(五):数据库(一)
  • windows docker 中的mysql 无法被外部浏览器访问如何解决
  • windows环境下安装dify到本地
  • 线程池、锁策略
  • Qt中UDP回显服务器和客户端
  • 第三十二天:数组
  • 如何保证redis和mysql的数据一致性
  • Spring Boot 3.x 微服务架构实战指南
  • 基于单片机停车场管理系统/车位管理/智慧停车系统