07 C#之 深刻理解类

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]}");

        }

    }

你可能感兴趣的:(07 C#之 深刻理解类)