C#——刘铁猛笔记
类、名称空间(简述)
类(class)是构成程序的主体
名称空间(namespace)以树形结构组织类(其他类型)
名称空间:名称空间是用来组织和管理类、接口、结构体等类型的逻辑容器。它可以帮助开发人员避免命名冲突,将相关的类型组织在一起,提高代码的可读性和可维护性。名称空间可以嵌套使用,形成层次结构。在C#中,使用namespace关键字来定义名称空间。
打个比方:
在一个图书馆中,每本书都会有它专属的类放置在一个特定的位置上,那么名称空间就相当于一个图书馆,类就相当于书的类。不同的图书馆有些书的类一样,但其所含书本不一样,因此名称空间也能防止类的名字冲突。
当程序中的一个名称空间中,想要使用另一个名称空间的某一个方法时,需要在程序中名称空间的外部使用using引用所需的名称空间,或者在该名称空间中写出所需名称空间的限定名称。
namespace HelloWorld
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
当引用的名称空间中有两种或两种以上的名称空间中包含同名的类,使用这个类时也需要写出限制性名称。
类库
类库引用时使用名称空间的物理基础,使用名称空间时,可以点开References(引用)来检查是否有包含该名称空间的类库(类库简称dll)
在C#中,类库(Class Library)指的是一组封装了一些相关功能的类、接口和其他类型的集合。类库通常用于封装通用的功能,以便在多个应用程序中重复使用。
类库可以包含各种类型的功能,例如数据结构、算法、I/O操作、网络通信、图形界面控件等。C#本身提供了一些标准的类库,如.NET Framework中的类库,它包含了大量的基本功能和工具类,用于支持C#程序的开发。
除了使用.NET Framework提供的类库之外,开发人员也可以自己编写类库,以封装自己的功能并在不同的项目中重复使用。这样可以提高代码的复用性,降低开发成本,同时也有利于代码的维护和管理。
在C#中,类库通常以DLL(Dynamic Link Library)的形式存在,可以通过引用的方式在C#项目中使用。通过引用类库,开发人员可以轻松地使用其中封装的功能,而无需关心具体的实现细节,从而提高开发效率并降低代码的重复编写。
一个类库可以包含一个或多个名称空间,用于组织其中的类型。
黑盒引用(无法看源代码)
黑盒引用(Black Box Reference):指的是只能通过接口或基类来引用对象的方式。在黑盒引用中,只能访问对象的公共成员或通过接口暴露的方法,而无法直接访问对象的私有成员或实现细节。这种引用方式更加封装和安全,符合面向对象编程的封装原则。
-
引用一个类库时,右击reference
-
引用一个类库时,它可能受限于更底层的类库,因此引用时还需要引用其更底层的类库,为了避免这个麻烦,可以引用NuGet,类似于一个类库包。
白盒引用
白盒引用(White Box Reference):指的是可以直接访问对象的私有成员或实现细节的引用方式。在白盒引用中,可以直接访问对象的所有成员,包括私有成员和实现细节。这种引用方式可能会破坏对象的封装性,增加耦合度,不利于代码的维护和扩展。
引用自己已有的项目,此时需要将该项目添加到自己的solution里面,之后再右击reference,再solution里勾选该类库。
图中有新建项和现有项,若要使用新建项,在打开时就要选择class library项目。
总的来说,黑盒引用更符合面向对象编程的封装和抽象原则,而白盒引用则更容易导致代码的耦合和依赖性。在设计和编写代码时,应该尽量使用黑盒引用,只暴露必要的接口和方法,避免直接暴露对象的内部实现细节。
依赖关系
在C#中,依赖关系指的是一个类或对象在实现功能时依赖于另一个类或对象的情况。依赖关系是面向对象编程中的一个重要概念,它描述了一个对象使用另一个对象提供的功能或服务的情况。
依赖关系通常体现在类之间的关联或调用关系上。当一个类需要使用另一个类的功能时,它就会依赖于这个类。这种依赖关系可以通过构造函数注入、属性注入或方法参数传递等方式来实现。
依赖关系的存在可以带来一些好处,如提高代码的复用性、降低耦合度、便于单元测试等。但如果依赖关系设计不当,可能会导致代码的脆弱性、难以维护和扩展等问题。
在实际开发中,我们通常会借助依赖注入(Dependency Injection)等技术来管理和解决类之间的依赖关系,以提高代码的可维护性和灵活性。通过合理设计和管理依赖关系,可以使代码更加模块化、可测试和可扩展。
类、对象、类与对象的关系
类
类(Class)是一种模板或蓝图,用于描述对象的属性和行为。类定义了对象的结构和行为,包括属性(字段)和方法。在C#中,类是定义对象的基本单位,通过类可以创建对象的实例。
对象
在C#中,对象(Object)是类的实例化(Instance)结果,是内存中的一个具体实体,具有属性和行为。对象是类的具体化,通过实例化类可以创建对象。对象在内存中占据一定的空间,包含了类中定义的属性和方法的具体数值和实现。
类与对象的关系
- 类是对象的模板,定义了对象的属性和行为,描述了对象的结构。
- 对象是类的实例化结果,是类的具体实体,具有类定义的属性和行为。
- 通过类可以创建多个对象,每个对象都是类的一个实例,但它们在内存中是独立存在的,各自拥有自己的属性值。
- 类定义了对象的结构和行为,而对象是类的具体化,实际应用中我们操作的是对象。
简单来说,就是你自己写了一个类,这个类就像一个概念一样,它包含着一些用来形容这个概念的东西,你想要使用这个类时候,你就需要创建一个对象,之后用这个对象来进行你后续的操作。
比如你写了一个飞机的类,但这个类是个概念,你能开概念吗?肯定不行,你要开的是飞机这个机器,所以你就要创建一个飞机开。
类的三大成员
前三个后面会详细说明
小知识–使用MSDN文档
把光标移到你所使用的类上,按f1键
静态成员与非静态成员
静态成员是属于类的成员,而不是属于类的实例(对象)的成员。静态成员可以被类的所有实例共享,可以通过类名直接访问,不需要创建类的实例。在内存中,静态成员只有一份拷贝,被所有实例共享。
非静态成员则是属于类的实例(对象)的成员,每个对象都有自己的一份。非静态成员需要通过对象来访问,每个对象都有自己的非静态成员的拷贝。
构成c#的语言的基本元素:关键字,操作符,标识符,标识符号,文本,注释。
小知识–声明变量和类时名称的要求
声明变量时变量名采用驼峰命名法,即首单词字母要小写,后续单词字母大写
声明一个类时名称时,单词都要大写
类型
什么是类型
强类型语言、弱类型语言
强类型指的是声明的变量是什么类型,以后它就是什么类型,弱类型指声明的变量可以是多个类型
-
强类型语言是指在编程时要求严格定义变量的数据类型,不允许不同类型之间的隐式转换。
-
在强类型语言中,变量的数据类型必须在编译时就确定,并且不会发生自动类型转换。
-
强类型语言通常具有更严格的类型检查,能够在编译时捕获一些潜在的类型错误。
-
弱类型语言是指在编程时对变量的数据类型要求较为灵活,允许不同类型之间的隐式转换。
-
在弱类型语言中,变量的数据类型通常可以在运行时动态确定,允许自动类型转换。
-
弱类型语言通常具有更灵活的类型系统,但也可能导致一些难以发现的类型错误。
小知识–c#中用dynamic定义的变量可以让该变量在不同时刻赋任何类型的值。
namespace DynamicSample
{
internal class Program
{
static void Main(string[] args)
{
dynamic myVar = 100;
Console.WriteLine(myVar);
myVar = "Mr.Okay!";
Console.WriteLine(myVar);
}
}
}
类型在C#语言中的作用
C#语言的类型系统–五大数据类型
变量
变量是以变量名为对应的内存地址为起点,以其数据类型所要求的存储空间为长度的一块内存区域(变量名中要么存储的是值类型的值,或者引用类型的地址)。
静态变量
- 静态变量属于类,而不是类的特定实例。
- 静态变量在类加载时被初始化,只有一份存储空间,所有类的实例共享同一份静态变量。
- 静态变量使用static关键字声明,在内存中存储在静态存储区域。
- 可以通过类名直接访问静态变量,无需实例化对象。
- 通常用于存储类级别的信息,如常量、计数器等。
实例变量
- 实例变量属于类的实例(对象),每个对象都有自己的实例变量副本。
- 实例变量在创建对象时被分配内存空间,并随着对象的销毁而释放。
- 实例变量不使用static关键字声明,每个对象都有自己的实例变量。
- 必须通过对象实例来访问实例变量。
数组元素
数组元素(Array Element):数组是一种数据结构,用于存储相同类型的多个元素。数组元素指的是数组中的单个数据项,通过索引访问。例如,对于整型数组 int[] numbers = {1, 2, 3, 4, 5};,numbers[0] 表示数组 numbers 中的第一个元素,其值为 1。
值参数
值参数(Value Parameter):值参数是一种参数传递方式,将参数的值传递给方法。在方法内部对值参数的修改不会影响到原始值。在方法签名中,参数前没有 ref 或 out 关键字的参数均为值参数。
引用参数
引用参数(Reference Parameter):引用参数是一种参数传递方式,将参数的引用传递给方法,使得在方法内部对参数的修改会影响到原始值。在方法签名中,参数前加上 ref 关键字表示引用参数。
输出参数
输出参数(Output Parameter):输出参数是一种特殊的引用参数,用于从方法中返回多个值。在方法签名中,参数前加上 out 关键字表示输出参数,调用方法时必须为输出参数赋值。
局部变量
局部变量(Local Variable):局部变量是在方法、构造函数或代码块内部声明的变量,只在声明的作用域内有效。局部变量在声明时必须初始化,可以在声明时或稍后赋值。
值类型、引用类型声明的变量在内存中的分配
值类型在内存分配的时候会根据该类型所需的空间来分配字节,引用类型在内存分配的时候只会分配四个字节,没有引用实例时该字节的二进制都是零,当创建实例后会把堆内存的地址放进该变量中,在堆内存中分配空间时才会计算该变量真正所需要的空间。
变量的默认值
成员变量分配好空间后不赋值时会自动都赋值成0,但本地变量不赋值会报错。
装箱和拆箱
装箱:当一个引用类型的变量发现赋予的值时放在栈上的值类型的值,那么其会在堆中的一个空位置上存储这个值,并把该位置的地址赋值给引用类型的变量上。
-
装箱是将值类型转换为引用类型的过程。
-
当将值类型赋值给一个对象类型(如 object)时,会发生装箱操作,将值类型的数据包装在一个堆分配的对象中。
-
装箱会导致性能开销,因为需要在堆上分配内存来存储值类型的数据,并且需要进行数据复制。
拆箱:当一个值类型的变量发现赋予的值时引用类型,那么其会根据地址找到该值赋给自己
- 拆箱是将引用类型转换为值类型的过程。
- 当从对象类型(如 object)中获取值类型数据时,需要进行拆箱操作,将包装在对象中的数据提取出来转换为值类型。
- 拆箱需要进行类型检查和数据复制,可能会导致性能开销。
方法
方法的由来
方法的声明与调用
当一个函数以类的成员出现时简称为方法
构造器
什么是构造器
在 C# 中,构造器(Constructor)是一种特殊类型的方法,用于在创建类的实例(对象)时初始化对象的状态。构造器的作用是初始化对象的成员变量、属性或执行其他必要的初始化操作。以下是构造器的一些特点:
命名与特点:
-
构造器的名称与类名相同。
-
构造器没有返回类型,包括 void。
-
构造器可以重载,即同一个类可以有多个不同参数列表的构造器。
初始化对象:
- 在实例化对象时,构造器会被自动调用,用于初始化对象的状态。
- 构造器可以初始化对象的成员变量、属性,或执行其他必要的初始化操作。
默认构造器:
- 如果没有显式定义构造器,C# 会提供一个默认构造器(无参数构造器),用于初始化对象。
- 如果显式定义了带参数的构造器,但没有定义无参数构造器,那么默认构造器就不会被提供。
对象的创建
当通过 new 关键字创建一个类的实例时,会在内存中分配一块空间来存储该对象的数据。这个空间包括对象的字段、属性和方法等信息。
构造器的调用
在对象创建的过程中,会调用构造器来初始化对象的各个部分。构造器可以有多个重载形式,根据参数列表的不同进行选择调用。
内存分配
在调用构造器之前,系统会先为对象分配内存空间。构造器负责对这块内存空间进行初始化,包括对字段、属性等成员变量的赋值操作。
构造器的执行顺序
如果类的继承关系中包含父类和子类,构造器的执行顺序是先执行父类的构造器,然后执行子类的构造器。这确保了对象的所有部分都能得到正确的初始化。
构造器的作用
构造器可以用来初始化对象的状态,进行一些必要的设置操作,确保对象在创建后处于一个合理的状态。
快捷生成构造器
//创建构造器快捷键
//ctor 按两下tab键
public Student(int initId,string initName)
{
}
声明无参数构造器(也可以称作默认构造器)
namespace ConstructorExample
{
class Program
{
static void Main(string[] args)
{
Student stu2 = new Student();
Console.WriteLine(stu2.ID);
Console.WriteLine(stu2.Name);
}
}
class Student
{
//创建构造器快捷键
//ctor 按两下tab键
public Student()
{
this.ID = 1;
this.Name = "No name";
}
public int ID;
public string Name;
}
}
声明带参数的构造器(实例化一个对象时必须对构造器内的成员赋值)
为了防止声明一个类时忘记对其字段赋值,可以使用带参数的构造函数。
namespace ConstructorExample
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student(2,"Mr.Okay");
Console.WriteLine(stu.ID);
Console.WriteLine(stu.Name);
}
}
class Student
{
//声明
public Student(int initId, string initName)
{
this.ID = initId;
this.Name = initName;
}
public int ID;
public string Name;
}
}
重载
什么是重载
方法的重载(Method Overloading)是指在同一个类中可以定义多个具有相同名称但参数列表不同的方法。通过方法重载,可以在同一个类中使用相同的方法名来执行不同的操作,根据传入的参数列表的不同来确定调用哪个方法。
比如Console.WriteLine就是一种重载,可以输出多种类型
小知识–Debug操作
设置断点,当摁f5时会在设置的断点处停止运行
此时调用堆栈中第一行是该函数,第二行是调用该函数的位置
Step-in是一个语句一个语句进行,Step-over是若该断点在是一个调用函数,直接返回调用函数后的结果,Steo-out是寻找调用该函数的地方。
操作符
越靠上的操作符优先级越高,越靠下的操作符优先级越低
什么是操作符?
操作符不能脱离与它关联的数据类型
namespace CreateOperator
{
internal class Program
{
static void Main(string[] args)
{
int x = 5;
int y = 4;
int z = x / y;
Console.WriteLine(z);
double a = 5.0;
double b = 4.0;
double c = a / b;
Console.WriteLine(c);
}
}
}
演示结果
2
Mr.Okay
请按任意键继续. . .
简记法
namespace CreateOperator
{
internal class Program
{
static void Main(string[] args)
{
Person person1 = new Person();
Person person2 = new Person();
person1.Name = "Dear";
person2.Name = "Dear's wife";
List<Person> nation = person1+ person2;
foreach(var p in nation)
{
Console.WriteLine(p.Name);
}
}
}
//创建一个类型
class Person
{
public string Name;
//public static List<Person> GetMarry(Person p1, Person p2)
//简记法————如下
public static List<Person> operator +(Person p1, Person p2)
{
List<Person> people = new List<Person>();
people.Add(p1);
people.Add(p2);
for(int i = 0; i < 11; i++)
{
Person child = new Person();
child.Name = p1.Name + "&" + p2.Name + "s child";
people.Add(child);
}
return people;
}
}
}
演示结果
Dear
Dear's wife
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
Dear&Dear's wifes child
请按任意键继续. . .
优先级与运算顺序
同优先级操作符从左到右
列如:
namespace OperatorPriority
{
internal class Program
{
static void Main(string[] args)
{
int x;
x = 3 + 4 + 5;
Console.WriteLine(x);
}
}
}
结果
12
请按任意键继续. . .
带有赋值功能的操作符的运算顺序都是从右向左
代码:
namespace OperatorPriority
{
internal class Program
{
static void Main(string[] args)
{
int x = 100;
int y = 200;
int z = 300;
x += y += z;
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);
}
}
}
600
500
300
请按任意键继续. . .
外层命名空间的子集命名空间(静态成员属于类)
各个操作符的作用
x.y 操作符:访问外层名称空间中的子名称空间,访问名称空间中的类型,访问类型中的静态成员,访问对象的成员。
//System.IO.File.Create("D:\\HelloWorld.text");
Form myForm = new Form();
myForm.Text = "Hello,World!";
myForm.ShowDialog();
f(x) 操作符:方法调用
a[x] 操作符:元素访问操作符
new 操作符:在内存中构造一个类型的实例,并且立刻调用这个实例的实例构造器(或初始化器),如果在new操作符有赋值符号时,会把该实例的内存地址赋给该变量。
在C#中,并不是构造类型时都需要使用new操作符,c#会在常用的类型构建实例时省去new操作符。
new操作符也可用于方法的继承和派生(让子类隐藏父类)
typeof 操作符:查看一个类型的内部结构
enum 枚举类型
default 操作符:获取一个类型的默认值
checked 操作符:用于检测程序运行时有没有类型溢出
unchecked 操作符:不检测程序运行时有没有类型溢出
checked和unchecked不仅有操作符用法,还有上下文用法
delegate 操作符:一般用于委托,在当作操作符时是用来声明匿名方法,该方法是只执行一次
委托——代码演示:
namespace OperatorsExample
{
internal class Program
{
static void Main(string[] args)
{
//委托
Calculator c = new Calculator();
Action myAction = new Action(c.PrintHello);
myAction();
}
}
class Calculator
{
public void PrintHello()
{
Console.WriteLine("Hello");
}
}
}
结果:Hello
default类型
var关键字 功能 帮忙声明隐式声明变量
namespace OperatorsExample
{
internal class Program
{
static void Main(string[] args)
{
//Dictionary类里的value值类型是Student
Dictionary<string,Student> stuDic = new Dictionary<string, Student>();
for(int i = 1;i<= 100; i++)
{
Student stu = new Student();
stu.Name = "s_" + i.ToString();
stu.Score = 100 + i;
stuDic.Add(stu.Name, stu);
}
Student number6 = stuDic["s_6"];
Console.WriteLine(number6.Score);
}
}
class Student
{
public string Name;
public int Score;
}
}
new 操作符:在内存中构造一个类型的实例,并且立刻调用这个实例的实例构造器(或初始化器),如果在new操作符有赋值符号时,会把该实例的内存地址赋给该变量。
new操作符和var关键字的用法:是为匿名类型创建对象,用隐式类型变量来引用实例
namespace OperatorsExample
{
internal class Program
{
static void Main(string[] args)
{
Form myForm = new Form() { Text = "Hello" };
//是为匿名类型创建对象,用隐式类型变量来引用实例
var person = new { Name = "Qi", Age = 21 };
Console.WriteLine(person.Name);
Console.WriteLine(person.Age);
Console.WriteLine(person.GetType().Name);
}
}
}
拓展类与类之间的继承
namespace OperatorsExample
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student();
stu.Report();
CsStudent csStu = new CsStudent();
csStu.Report();
}
}
class Student
{
public void Report()
{
Console.WriteLine("I'm a student");
}
}
class CsStudent : Student
{
//重写 子类隐藏父类
new public void Report()
{
Console.WriteLine("I'm CS student");
}
}
}
检查异常
delegate 操作符:一般用于委托,在当作操作符时是用来声明匿名方法,该方法是只执行一次
改进为
->操作符
下去自己练习
类型转换
sizeof 操作符:用于查询结构体类型的字节长度,其也可以检测自定义的结构体类型的字节长度,但要放在不安全的上下文中。
& 操作符:取地址操作符,取某个对象的地址。
- 操作符:找到指针所指向的变量
~ 操作符:取反操作符。
- 操作符:取反操作后+1。
(T)x 操作符:强制转换操作符
<< >> 操作符:<< 操作符补进来的都是0,>>操作符正数补进来的是0,负数补进来的是1
is 操作符:用于检测一个对象是不是某一类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Student stu = new Student();
bool res = stu is Student;
Console.WriteLine(res);//True
Student stu2 = null;
res = stu2 is Student;
Console.WriteLine(res);//false
res = stu is Animal;
Console.WriteLine(res);//True
Human human = new Human();
res = human is Student;
Console.WriteLine(res);//False
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
class Human : Animal
{
public void Think()
{
Console.WriteLine("Thinking...");
}
}
class Student:Human
{
public void Study()
{
Console.WriteLine("I want to play");
}
}
}
as 操作符(强制类型转化)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
object o = new Student();
Student stu = o as Student;//如果o是Student类型,那么就把该地址赋值给stu,否则赋值null;
if(stu!=null)
{
stu.Study();
}
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
class Human : Animal
{
public void Think()
{
Console.WriteLine("Thinking...");
}
}
class Student:Human
{
public void Study()
{
Console.WriteLine("I want to play");
}
}
}
?? 操作符:通常情况下值类型不能赋值null,但Nullable<数据类型>声明的变量可以,或者在值类型后加一个? 。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Nullable<int> x = null;
int? y = null;
Console.WriteLine(x);
Console.WriteLine(x.HasValue);
x = x ?? 1;//如果x是null值,那就把x赋值成1;
Console.WriteLine(x);
}
}
}
?: 操作符:if,else的简写
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
int x = 80;
string s = String.Empty;
s = x >= 60 ? "Pass" : "False";//如果真就返回:前面的值,否则返回:后面的值
Console.WriteLine(s);
}
}
}
类型转换
隐式类型转换
代码演示:
namespace ConversionExample
{
internal class Program
{
static void Main(string[] args)
{
int x = int.MaxValue;
//小往大转就隐式
long y = x;
Console.WriteLine(y);
}
}
}
结果
2147483647
请按任意键继续. . .
子类向父类转换
namespace ConversionExample
{
internal class Program
{
static void Main(string[] args)
{
Teacher t = new Teacher();
Human h = t;
Animal a = h;
a.Eat();
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("Eating...");
}
}
class Human : Animal
{
public void Think()
{
Console.WriteLine("Who I am?");
}
}
class Teacher : Human
{
public void Teach()
{
Console.WriteLine("I teach programming");
}
}
}
显示类型转换
显示类型转换就是在转换对象中构造一个目标类型对象的构造器
namespace ConversionExample
{
internal class Program
{
static void Main(string[] args)
{
Stone stone = new Stone();
stone.Age = 5000;
//隐式类型转换 Monkey wukongSun = stone;
Monkey wukongSun = (Monkey)stone;
Console.WriteLine(wukongSun.Age);
}
}
class Stone
{
public int Age;
//隐式类型转换 public static implicit operator Monkey(Stone stone)
//显示类型转换
public static explicit operator Monkey(Stone stone)
{
Monkey m = new Monkey();
m.Age = stone.Age/500;
return m;
}
}
class Monkey
{
public int Age;
}
}
tips:将explici改成implicit后就能把显式类型转变成隐式类型。
表达式
表达式是一种专门求值的语法实体,可以有一个或多个操作数和零个或多个操作符组成
访问事件 An event access
索引访问表达式
语句
c#语句的定义
参考c#定义文档
虚线以上需要熟练使用
const常量的值是不能够被改变的
字段
C语言参考
代码小记:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataMemberExample
{
class Program
{
static void Main(string[] args)
{
List<Student> stuList = new List<Student>();
for(int i = 0; i < 100; i++)
{
Student stu = new Student();
stu.Age = 24;
stu.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.Amount;
Student.AverageScore = totalScore / Student.Amount;
Student.ReportAmount();
Student.ReportAverageAge();
Student.ReportAverageScore();
}
}
class Student
{
public int Age;//实例字段,创建的对象可用的成员变量
public int Score;
public readonly int id=100;//声明一个动态只读字段,只有一次机会对其赋值,就是在它的构造器中
//如果在创建的对象中没有对id进行赋值,那么id的值就是100,否则就是在构造器中赋予的值
public static readonly Color WColor = new Color() { red = 0, blue = 0, green = 0 };//声明一个静态只读字段
public static int AverageAge;//静态字段,仅类可用
public static int AverageScore;
public static int Amount;
public Student()
{
Student.Amount++;
}
public static void ReportAmount()
{
Console.WriteLine(Student.Amount);
}
public static void ReportAverageAge()
{
Console.WriteLine(Student.AverageAge);
}
public static void ReportAverageScore()
{
Console.WriteLine(Student.AverageScore);
}
}
}
静态只读字段也不能被复制 功能只能被实例保存
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Schema;
namespace DataMemberExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Brush.DefaultColor.Red);
Console.WriteLine(Brush.DefaultColor.Green);
Console.WriteLine(Brush.DefaultColor.Blue);
//静态初始化之后不能被赋值
//Brush.DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };
}
}
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 };
//静态构造函数里静态构造器
public static readonly Color DefaultColor;
static Brush()
{
Brush.DefaultColor = new Color() { Red = 0, Green = 0, Blue = 0 };
}
}
}
实例字段的初始化时机实在创建一个对象的时候进行,静态字段的初始化时机实在运行环境加载该数据类型的时候,并且静态字段的初始化执行一次,即第一次被加载的时候。
set与get方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PropertyExample
{
internal class Program
{
static void Main(string[] args)
{
Student stu1 = new Student();
stu1.Age = 20;
Student stu2 = new Student();
stu2.Age = 20;
Student stu3 = new Student();
stu3.Age = 200;
int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
Console.WriteLine(avgAge);
}
}
class Student
{
public int Age;
}
}
改进之后的方法 set与get方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace PropertyExample
{
internal class Program
{
static void Main(string[] args)
{
Student stu1 = new Student();
stu1.SetAge(20);
Student stu2 = new Student();
stu2.Set