07 C# -深刻理解类

本文探讨了C#中的类成员概念,包括数据成员和函数成员,重点介绍了静态成员(如静态字段、静态函数和静态构造函数)、实例成员(及其区别),并详细讲解了构造函数、属性、索引器的用法和特点。通过实例演示,展示了如何访问和操作这些关键概念。
摘要由CSDN通过智能技术生成

1.类成员

类成员分数据成员和函数成员,数据成员用于保存数据,函数成员用于执行代码。

类成员类型:字符,方法,运算符,常量,属性,索引,构造函数,析构函数,事件

2. 成员修饰符

[特性] [修饰符] 核心声明

特性:如果有特性,必须放在修饰符和核心声明之前;如果有多个特性,可任意顺序

修饰符:如果有修饰符,必须放在核心声明前;如果有多个修饰符,可任意顺序

static private int TestCount = 10;

private static int TestCount = 10; 这2中声明式等效的。

3. 实例成员

类成员可以关联到类的一个实例。类的每个实例拥有自己的各个类成员的副本—实例成员。改变一个实例字段的值不会影响任何其它实例中成员的值。

class MyDemoClass

{

public int TestValue;

}

class Program

{

static void Main(string[] args)

{

MyDemoClass d1 = new MyDemoClass();

d1.TestValue = 123;

MyDemoClass d2 = new MyDemoClass();

d2.TestValue = 456;

Console.WriteLine($“d1 value:{d1.TestValue}, d2 value:{d2.TestValue}”);

}

}

输出:

d1 value:123, d2 value:456

实例变量至于对应的实例关联 ,类的实例都有自己字段的副本。

堆上分配的内存

4. 静态字段

静态字段被类的所有实例共享,所有实例都访问同一内存位置。

使用static 修饰符将字段声明为静态

class MyDemoClass

{

public int TestValue;//实例字段

public static int StaticValue=999;//静态字段

}

5. 从类的外部访问静态成员

类名+点+成员名称 (MyDemoClass.StaticValue)

静态成员的生存周期

与实例成员不同,实例成员只有实例创建后才产生,实例销毁后实例成员就不存在了。

静态成员,即使没有实例,也存在,并可以访问。

6. 静态函数成员

静态函数成员也是独立于任何类实例的,即使没有实例,仍可以调用静态方法。

静态函数不能访问实例成员,但能访问其它静态成员。

class Demo

{

static public int x;// 静态字段

static public void PrintX()//静态方法

{

Console.WriteLine($“Value of X:{x}”);

}

}

测试:

class Program

{

static void Main(string[] args)

{

Demo.x = 66;//使用句点语法

Demo.PrintX();//使用句点语法

}

}

7. 其它静态类成员类型


可声明为静态的类成员类型

8. 成员常量


成员常量类似本地常量,只是它被声明在类中,而不是在方法内。

初始化成员常量的值在编译时必须是可计算的,而且通常是一个预定义简单类型或者他们组成的表达式。

在类中声明:

const int Val = 100;// 定义int 类型常量,初始值100

与C,C++不同,在C#中没有全局常量,每个常量都必须声明在类中。

const int IntVal;// 错误,必须初始化

IntVal=100;//错误,不允许赋值

9. 常量与静态量


成员常量:表现想静态只,但不能使用 static声明。与静态常量不同,没有自己的存储位置,而是编译时被编译器替换。

静态常量

public const double PI = 3.1415;// 常量

使用:类名.PI

10. 属性

属性是代表类的实例或者类中的一个数据项的成员。

属性与字段类型,有如下特征:

它是命名的类成员

它有类型

它可以被赋值和读取

然而字段只属于一个函数成员,它不为数据存储分配内存空间

属性是指定的一组2个匹配的,访问器的方法:

set访问器为属性赋值,get访问器从属性取值。

属性声明和访问器

class Demo

{

private int FiledValue;//字段,分配内存(后备字段)

public int MyValue //属性,未分配内存

{

set { FiledValue = value; }

get { return FiledValue; }

}

}

使用属性

Demo d = new Demo();

d.MyValue = 20;//Set 赋值

Console.WriteLine($"{d.MyValue}");

属性和关联字段

常见的方式是在类中将字段声明为private以封装字段,并声明一个public熟悉控制从类外部对该字段的访问。

和熟悉关联的字段常被称作后备字段或后备存储。

属性定义的2中常见方式,使用Pascal大小写,Camel大小写版本

private string name;

public string Name

{

get { return name; }

set { name = value; }

}

private string _name;

public string Name

{

get { return _name; }

set { _name = value; }

}

执行其它计算

访问器get,set  能执行任何计算,也可以不执行任何计算,唯一需求行为是get访问器需要返回一个属性类型的值。

public int MyValue

{

set { }//什么也不设置

get { return 100; }//只是返回100

}

private int _myValue2;

public int MyValue2

{

get { return _myValue2; }

set

{

MyValue2 = value > 100 ? 100 : value;//条件运算

}

}

C# 7.0引入了另一种语法,表达式函数体(Lambda表示)

private int score;

private int Score

{

set => score>100?100 : value;

get => score;

}

只读和只写属性

只有get 访问器的属性称为只读属性

只有set访问器的属性称为只写属性(很少见,几乎没有实际用途)

两个访问器中至少有一个必须定义,否则编译器产生错误。

属性与共有字段

属性是函数成员,而不是数据成员,允许输入输出。

属性可以是只读或只写,字段不可以。

编译后的变量和编译后的属性语义不同。

自动实现属性

只声明属性,不声明后备字段。编译器自动创建隐藏后备字段。

public string lastName { get; set; }

静态属性

属性声明为static,和静态成员一样:

不能访问类的实例成员,但能被实例成员访问。

不管类是否有实例,它们都是存在的。

在类的内部,可以仅使用名称来引用静态属性。

class Test

{

public static int MyValue { get; set; }

public void PrintValue()

{

Console.WriteLine($“Value from inside:{MyValue}”);// 类的内部访问

}

测试:

//类的外部访问

Console.WriteLine($“Initial Value:{Test.MyValue}”);

Test.MyValue = 20;

Console.WriteLine($“New Value:{Test.MyValue}”);

11. 实例构造函数


实例构造函数是一个特殊的方法,它在创建类的每个新实例时执行。

构造函数用于初始化类实例的状态

如果需要从类的外部创建类的实例,需要声明为public

构造函数的名称和类同名

构造函数不能有返回值

带参数的构造函数

构造函数可以带参数

构造函数可以被重装

public class Demo

{

int id;

string name;

public Demo() { id = 1; name = “name1”; }// 无参构造函数

public Demo(int ID) { id = ID; name = “testName2”; }//带一个参数的构造函数

public Demo(int Id,string Name) { id = Id; name = Name; }//带2个参数的构造函数

public void ShowMessage()

{

Console.WriteLine($“Name:{name}, Id:{id}”);

}

}

测试上演示类:

class Program

{

static void Main(string[] args)

{

Demo d1 = new Demo();

d1.ShowMessage();

Demo d2 = new Demo(123);

d2.ShowMessage();

Demo d3 = new Demo(456, “MyName”);

d3.ShowMessage();

}

}

默认构造函数

没有参数;方法体为空

如果类声明了任何构造函数,编译器就不会创建默认的构造函数。

静态构造函数

构造函数也可以声明为static,实例构造函数初始化类的每个实例,而静态构造函数初始化类级别的项。通常静态构造函数初始化类的静态字段。

类只能有且只能有一个构造函数,且不能带有参数,静态构造函数不能有访问修饰符。

类即可有静态构造函数,也可以有实例构造函数。

静态构造函数不能访问任何实例成员,因此也不能使用this访问器

不能从程序中显示调用静态构造函数,系统会自动调用它们。

class RandomNumber

{

private static Random RandomKey;//私有静态变量

static RandomNumber() // 静态构造函数

{

RandomKey = new Random();

}

public int GetRandKeyNumbers()

{

return RandomKey.Next();

}

}

测试调用:

class Program

{

static void Main(string[] args)

{

RandomNumber rndN1 = new RandomNumber();

RandomNumber rndN2 = new RandomNumber();

Console.WriteLine($“Next Random #{rndN1.GetRandKeyNumbers()}”);

Console.WriteLine($“Next Random #{rndN2.GetRandKeyNumbers()}”);

}

}

输出:

Next Random #365872672

Next Random #1403081881

对象初始化语句

new TypeName {Field1=InitExpr1, Filed2=InitExpr2} //对象初始化语句

new TypeName(ArgList) {Field1=InitExpr1, Filed2=InitExpr2} //成员初始化语句

析构函数

析构函数destructor 执行的类在实例被销毁之前需要的清理或释放非托管资源的行为。

readonly 修饰符

const字段只能在字段的声明语句中初始化,而readonly字段可在如下任意位置设置:

字段声明语句

类的任何构造函数

const字段的值必须可在编译时决定,而readonly字段的值可在运行时决定。

const的行为总时静态的,对于readonly字段可以是静态字段,也可是实例字段,在内存中有存储位置。

readonly double PI=3.1415;

12. This 关键字


对当前实例的引用,只能被用在下列类成员的代码块中:

实例构造函数

实例方法

属性和索引器的实例访问

所以不能在任何静态函数成员的代码中使用。

使用this的目的:

用于区分类的成员和局部变量或参数。

作为调用方法的实参。

13. 索引器

什么是索引器:索引器是一组get和set访问器,与属性类似。

索引器和属性:

索引器和属性一样不用分配内存来存储

索引器和属性都主要被用来访问其它数据成员。

属性通常表示单个数据成员,索引器通常表示多个数据成员。

声明索引器:

索引器没有名称。在名称的位置是关键字this。参数列表在方括号中间;参数列表中必须至少声明一个参数。

ReturnType  this[Type param,…]

{

get {…}

set {…}

}

索引器的set 访问器

当索引器被用于赋值时,set访问器被调用。

索引器的get 访问器

当索引器获取值时,可以通过一个或多个参数调用get访问器。

不能显示调用get,set访问器。

class Employee

{

public string FirstName;

public string LastName;

public string CityOfBirth;

//以上代码是没有索引的简单类

//声明一个索引器

public string this[int index]

{

set

{

switch (index)

{

case 0:

FirstName = value;

break;

case 1:

LastName = value;

break;

case 2:

CityOfBirth = value;

break;

default:

throw new ArgumentOutOfRangeException(“index”);

}

}

get

{

switch (index)

{

case 0:

return FirstName;

case 1: return LastName;

case 2: return CityOfBirth;

default:

throw new ArgumentOutOfRangeException(“index”);

}

}

}

}

测试代码:

class Program

{

static void Main(string[] args)

{

Employee ep = new Employee();

ep.FirstName = “Jane”;

ep.LastName = “Doe”;

ep.CityOfBirth = “Dallas”;

Console.WriteLine($"{ep.LastName} {ep.FirstName} {ep.CityOfBirth}");

// 使用索引器

Console.WriteLine($"{ep[0]} {ep[1]} {ep[2]}");

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flysh05

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值