C#基础——类

  学习C#.net已有一段时间了,学的快忘的也快,在博客园开博也是很久很久了,是时候留下点东西了,从这篇笔记开始,将对前面所学编程知识进行复习。要知道,想让我坚持一件事情是很不容易的,我不知道这次能走多远--第1天就这样兢兢战战滴来了!

类是C#中的一种特殊又复杂的数据类型,但是不要怕,没那么简单,也没那么难!

C#中如何定义类

class Person
{
}
默认情况下,class关键字前没有写访问修饰符,那类的访问修饰符就是internal,当然也可以写上,但这又是没有必要的,默认就是internal嘛。
当然类还可以指定其他访问修饰符:public、private、protected、abstract、sealed等,还可以组合使用。
1、C#类的成员

类的成员包括字段、属性、方法、构造函数等。
这些成员也可设置访问权限,和类一样。
还可以使用static关键字将其声明为静态成员。静态成员属类级别概念,它不属于类的实例(对象)。

2.1、 字段

字段由三部分组成:访问修饰符、字段类型、字段名称。
字段一般声明为private

1 public class Person 2 { 3   private string name; 4   public int age; 5   protected bool sex; 6 }

用关键字readonly或const定义字段

1 public class Person 2 { 3   private readonly string name;//只读字段,不需要在定义时初始化,可在构造函数中完成初始化

4   public const int age=18;//加了const就要给定初始化值

5   protected bool sex; 6 }

使用关键字static来声明静态字段。
静态字段和实例字段的区别是:静态字段必须通过类.字段名访问,实例名则通过类的对象.字段名

1 public class Person 2 { 3     public static string name;//静态成员字段

4     public const int age=18;//实例成员字段

5 }

2.2 属性

属性是字段的扩展。
为了不让外界随意修改成员的值,最好将字段设置为private。
C#中提供了一种属性机制,可以灵活的控制外界对字段的读写。

 1 public class Person  2  {  3         private string name;  4         //方法是类的“行为”,接受外界设定的“名字”值

 5         public void SetName(string value)  6  {  7             this.name = value;  8  }  9         //返回字段name的值

10         public string GetName() 11  { 12             return this.name; 13  } 14         private int age; 15         //方法是类的“行为”,接受外界设定的“年龄”等值

16         public void SetAge(int value) 17  { 18             this.age = value; 19  } 20         //返回字段age的值

21         public int GetAge() 22  { 23             return this.age; 24  } 25         //执行问好的动作

26         public void SayHello() 27  { 28             Console.WriteLine("大家好,我是" + this.name + ",我今年" + this.age + "岁了"); 29  } 30         //上面对字段的读取和写入是用方法实现. 31         //而C#提供的属性机制更方便,使我们不用再麻烦的调用方法就可以对字段进行读写。

32         public string Name 33  { 34             get { return name; } 35             set { name = value; } 36  } 37         //简写

38         public string Name { get; set; } 39     }

可以使用只写get或给set设置private来定义只读属性,只写属性也一样。但只是不能被外界读取(比如Main方法不能读取它)

还可以给属性加入逻辑控制代码,比如人的年龄一般在0-120之间,为了避免用户输入这个范围之外的数值,可在属性中添加限制代码或抛出异常代码。

 1         private int age;  2         public int Age  3  {  4             get

 5  {  6                 return age;  7  }  8             set

 9  { 10                 if (age <= 0 || age > 120) 11  { 12                     throw (new ArgumentOutOfRangeException("AgeIntPropery", value, "年龄必须在0-120之间")); 13  } 14                 age = value; 15  } 16         }    

 

2.3 方法

Main方法是每个C#应用程序的入口,程序启动时,Main由公共语言运行时(CLR)负责调用。
方法由方法签名和一系列语句的代码块组成。
方法就是一堆可以重复使用(复用)的代码段,执行过程中无法确定的数据以参数形式传递;方法执行的执行结果以返回值进行返回。
方法签名包括方法的访问级别(如public、private)、可修饰符(如abstract、static等)、方法名和参数来。
方法可以没有参数,可以没有返回值(void).return返回处理结果,执行return之后方法内部的代码就执行结束了。

 1 public class Person  2  {  3             //这是一个有参数无返回值的方法

 4             public static void SayHello()  5  {  6                 Console.WriteLine("大家好!");  7  }  8             //这是一个由参数有返回值的方法

 9             public int Print(int age) 10  { 11                 Console.WriteLine("我的年龄是" + age); 12                 return age; 13  } 14         }

因为定义的是实例方法,要调用实例方法必须实例化一个对象。
带有static关键字的方法叫做静态方法,静态方法属于类级别,不能通过实例进行访问,必须通过Person.SayHello()方式调用。

class Program { static void Main(string[] args) { Person p=new Person(); p.Print(18); Person.SayHello(); } }

方法的重载
同一个类中,允许存在一个以上的同名方法,只要其参数个数、参数类型或参数顺序不同即可。与返回值无关。

 1 class Program  2  {  3             static void Main(string[] args)  4        {  5         Person p = new Person();  6         //参数个数、类型、顺序不同区分调用哪一个方法重载

 7         p.Print("Lucy")  8         p.Print(1, "Sean");  9         p.Print("Jack", 2); 10         Console.ReadKey(); 11        } 12  } 13 public class Person 14  { 15             public int Print(int age) 16  { 17                 Console.WriteLine("年龄:" + age); 18                 return 100; 19  } 20             public void Print(string name) 21  { 22                 Console.WriteLine("我的名字叫:" + name); 23  } 24             public void Print(int age, string name) 25  { 26                 Console.WriteLine("我的名字叫:" + name + "年龄是:" + age); 27  } 28             public void Print(string name, int age) 29  { 30                 Console.WriteLine("我的名字是:" + name + "今年" + age); 31  } 32 }

构造函数
构造函数是创建对象,并且在创建完成前对类进行初始化的特殊函数。
有实例构造函数和静态构造函数两种。
特征:

  • 方法名必须和类名一致,
  • 无返回值。
  • 构造函数可以重载,Person(String name,int age)
  • 可以对实例构造函数指定访问级别,即可以使用public、protected和private修饰符来修饰。要构成实例构造函数,必须满足以下两个条件:必须和类同名;不允许有返回值。
  • 用构造函数初始化和new之后通过属性初始化的区别:
  • 有的对象生来就要有一些成员变量被赋值,否则就是怪胎。有些属性是出生时设置的,不能后期set改

也可以这么理解:
当你在主方法中new一个对象时,Person p=new Person();这个Person()是不是很像在调用一个方法(函数),这个方法(函数)其实就是构造方法,不写的话默认会给出一个无参构造方法;
那么构造方法怎么写:
因为在主方法中调用时是Person p=new Person(),显然要先读取Person这个类,那么构造函数也要和这个类名一致。

private和protected修饰的是私有构造函数

 1 class Program  2  {  3         static void Main(string[] args)  4  {  5             /*

 6  Person p = new Person();  7  //参数顺序和参数类型,参数个数不同都构成重载。  8  p.Print("Sean", 1);  9  p.Print(2, "Shawn");*/

10             //一般写了有参构造函数默认无参就没了,如果要用需要自己写出来

11             Person p1 = new Person(); 12             Person p2 = new Person("Sean"); 13             Person p3 = new Person() { Name = "Jack", Age = 18 };//简写的,属性赋值

14  Console.ReadKey(); 15  } 16  } 17     public class Person 18  { 19         private string name; 20         public string Name { get; set; } 21         private int age; 22         public int Age { get; set; } 23         public Person() 24  { 25             name = "Tom"; 26  } 27         public Person(string name)//这是公共构造函数

28  { 29             //使用this关键字来引用字段name,与参数name(局部变量)区别开来。

30             this.name = name;//this代表当前类的实例对象。

31  } 32     }

私有构造函数典型应用是设计模式中单例模式的实现:

 1  class Person  2 {  3     private string name;  4     public static Person person;  5     public string Name;  6  {  7         get{ return this.name;}  8  }  9 

10     //私有构造函数,只能在类内部调用 11     //也就是说类的实例化只能在类定义时被实例化

12     private Person() 13  { 14         this.name="sean"; 15  } 16     //静态方法,用于返回类的实例

17     public static Person GetInstance() 18  { 19         person = new Person(); 20         return person; 21  } 22 } 23 

24 class Program 25 { 26     static void Main(string[] args) 27  { 28         //通过调用GetInstance()静态方法返回一个Person的实例 29         //不能使用new Person()创建实例

30         Person person=Person.GetInstance(); 31         Console.WriteLine("类实例的属性为:"+person.Name); 32  Console.Read(); 33  } 34 }

 

静态构造函数

  • 静态构造函数用于初始化类中的静态成员,在实例构造函数或引用任何静态成员之前执行,
  • 静态构造函数只会执行一次。
  • 静态构造函数不能带有任何参数。
  • 静态构造函数不能使用任何访问修饰符
  • 不能直接调用静态构造函数。
  • 无法控制执行的时机。
  • 静态构造函数,在实例构造函数执行前执行

结合下面代码,在Main方法中,创建两个Person对象,启动程序会发现,首先打印的是“静态构造函数被调用了”,随后才是两个“实例构造函数被调用了”。

 1     private static string name;  2     //静态构造函数,仅执行一次

 3     public Person()  4  {  5             Console.WriteLine("实例构造函数被调用了");  6  }
7 static Person() 8 { 9 Console.WriteLine("静态构造函数被调用了"); 10 name="sean"; 11 } 12 public static string name 13 { 14 get{return name;} 15 }

 

析构函数
用于在类销毁之前释放实例所使用的托管和非托管资源。
定义析构函数,需要注意:

  • 不能再结构体中定义析构函数,只能对类使用析构函数。
  • 一个类只能有一个析构函数
  • 无法继承和重载析构函数
  • 无法显示调用析构函数,析构函数由垃圾回收器自动调用。
  • 析构函数既没有修饰符也没有参数
1 class Person 2 { 3     ~Person() 4  { 5         Console.WriteLine("析构函数被调用了"); 6  } 7 }

该析构函数隐式的调用了基类Object的Finalize方法,上面代码中的析构函数将隐式的转换为如下代码:

protected override void Finalize() { try { Console.WriteLine("析构函数被调用了"); } finally { //调用FinalLize方法

        base.Finalize(); } }

索引器 当一个类包含数组成员时,索引器的使用将大大简化对类中数组成员的访问。索引器的定义类似于属性,也具有get访问器和set访问器,代码示例:

[修饰符] 数据类型 this[索引类型 index] 

get{//返回类中数组某个元素} 
set{//对类中数组元素赋值} 

数据类型对应intarray字段的数据类型,索引类型表示该索引器使用哪一个类型的索引来存取数组元素,可以是整型,也可以是字符串;this表示所操作的是类对象的数组成员,可以简单理解为索引器的名字(注意,索引器不能自定义名称)

 

 1  class Person  2  {  3         //可容纳10个整数的数组

 4         private int[] intarray = new int[10];  5         //索引器的定义

 6         public int this[int index]  7  {  8             get

 9  { 10                 return intarray[index];//返回类中数组某个元素

11  } 12             set

13  { 14                 intarray[index] = value;//对类中数组元素赋值

15  } 16  } 17     }

如何使用索引器

Main方法中:

1 Person person = new Person(); 2 Person p3 = new Person(); 3 p3[0] = 15; 4 p3[1] = 32; 5 p3[2] = 20; 6 p3[3] = 19; 7 Console.WriteLine(p3[2]);

 


索引器和属性的区别:索引器也是一种对私有字段的一种访问,不同的是索引器是对数组类型的私有字段进行访问,而属性是对简单数据类型的一种访问。

3. 类和结构体的区别

  • 定义类要使用关键字class,结构体使用struct
  • 结构体不可对声明字段进行初始化。
  • 类默认有无参构造函数,并且为隐式函数。而在结构体中无论你是否显式定义了构造函数,隐式构造函数都一直存在。
  • 结构体中不能显式定义无参数构造函数,类可以显示定义一个无参构造函数同时会覆盖默认无参构造函数。
  • 结构体的构造函数中,必须给所有字段赋值。
  • 结构体不能继承结构或者类,但可以实现接口;类可以继承类但不能继承结构,可以实现接口。
  • 类是引用类型,结构体是值类型。
  • 结构体不能定义析构函数,类可以有析构函数。
  • 不能用abstract和sealed关键字修饰结构体,类可以。
 1  struct Point  2  {  3         private int x;  4         private int y;  5         public Point(int i1, int i2)  6  {  7             this.x = i1;  8             this.y = i2;  9  } 10     }

 

4.匿名类

C#中的匿名类: var p = new { Id=5,Name="rupeng",Age=8} 通过反编译看到其实还是生成一个类。

第一步:定义一个类,类有三个属性Id,Name,Age其类型根据=右边的值来推断。

第二步:创建这个类的对象,用这个变量p1指向它。

你可能感兴趣的:(C#)