Day 07
枚举
简单枚举
- 列举某种数据的所有取值。
- 作用:增强代码的可读性,限定取值。
- 语 法 : enum 名字{值1,值2,值3,值4}。
- 枚举元素默认为int, 准许使用的枚举类型有byte、sbyte、 short、ushort、int、uint、long或ulong。
- 每个枚举元素都是有枚举值。默认情况下,第一个枚举的 值为0,后面每个枚举的值一次递增1,可以修改值,后面枚举数的值依次递增。
标志枚举
- 可以同时赋多个枚举值。
- 条件:
–任意两个枚举值做按位或运算的结果不能与其他枚举值 相同。
–使用[Flags]特性标记枚举类型。
[Flags]//标志枚举
enum PersonStyle
{
tall = 1, //00000001
rich = 2, //00000010
handsome = 4, //00000100
white = 8, //00001000
beauty = 16 //00010000
}
按位运算符
1. 按位或运算:
- 对应的两个二进制位有一个为1时,结果位为1。
- 用于同时选择多个枚举值。
- 例 如 : 2 与 3 做按位或运算,结果仍然为3
0010 | 0011 --> 0011
2. 按位与运算:
- 对应的两个二进制位都为1时,结果位为1。
- 用于判断标志枚举是否包含某个枚举值。
- 例如:2 与3做按位或运算,结果仍然为3
0010 & 0011 --> 0010
注意
-
选择多个枚举值
运算符|(按位或): 两个对应的二进制位中有一个为1,结果位为1
tall | rich ==> 0000000000 | 0000000001 ==> 0000000001 -
条件:(枚举多选的时候两者要都写)
1 . 任意多个枚举值做 | 运算 的 结果,不能与其他枚举值相同 (值以2的n次方递增)
2 . 定义枚举时,使用 [Flagsh] 特性修饰 -
判断标志枚举 是否包含指定枚举值
运算符&(按位与):两个对应的二进制位中都为1,结果位为1
0000000011 & 0000000001 ==> 0000000001
static void Main1(string[] args)
{
// 数据类型
//(1)值类型:直接存储数据
//(2)引用类型: 存储数据的引用(内存地址)
//(3)方法执行在栈中,执行完毕清除栈帧。
//(4)局部变量的值类型:声明在栈中,数据在栈中
//(5)局部变量的引用类型:声明在栈中,数据在堆中,栈中存储数据的引用。
//(6)区分修改的是栈中存储的引用,还是堆中数据
PrintPersonStyle(PersonStyle.tall | PersonStyle.rich);
//数据类型转换
// int ==> Enum
PersonStyle style01 = (PersonStyle)2;
PrintPersonStyle((PersonStyle)2);
// Enum ==> int
int enumNumber = (int)(PersonStyle.beauty | PersonStyle.white);
//string ==> Enum
//"beauty"
PersonStyle style02 = (PersonStyle)Enum.Parse(typeof(PersonStyle), "beauty");
// Enum ==> string
string strEnum = PersonStyle.handsome.ToString();
}
//多选和包含
private static void PrintPersonStyle(PersonStyle style)
{
//多选
if (style == PersonStyle.tall)
Console.WriteLine("大个子");
if (style == PersonStyle.rich)
Console.WriteLine("土豪");
if (style == PersonStyle.handsome)
Console.WriteLine("英俊");
if (style == PersonStyle.white)
Console.WriteLine("洁白");
if (style == PersonStyle.beauty)
Console.WriteLine("漂亮");
//包含
if ((style & PersonStyle.tall) == (PersonStyle.tall))
Console.WriteLine("大个子");
}
类和对象
- 面向对象: 一种软件开发的思想,指导程序员如何分析、
解决问题。 - 类是一个抽象的概念,即为生活中的”类别”。
- 对象是类的具体实例,即归属于某个类别的”个体”。
- 例如:学生是一个类,表示一种类型,”xx同学”则是一个对象。
- 名词类型的共性,作为数据成员。
- 动词类型的共性,作为方法成员。
创建类
- 语法:
访问级别 class 类名
{
类成员...
}
- 通常每个类都在一个独立的 c# 源文件中。
- 创建新的类意味着在当前项目中产生了一种新的数据类型
创建对象
- 语法:
类名引用名;
引用名= new 构造函数(参数列表); - 创建对象的过程也称为”实例化”
访问修饰符
- 用于修饰类及类成员的访问可见范围。
public:所属类的成员以及非所属类的成员都可以访问。
private:只有所属类的成员才能访问。[类成员的默认级别]
属性
属性
- 对字段起保护作用,可实现只读、只写功能。
- 本质就是对字段的读取与写入方法。
- 语法:
[访问修饰符]数据类型属性名
{
get {
return 字段;}
set {
字段= value;}
}
- 通常一个公有属性和一个私有字段对应。
- 属性只是外壳,实际上操作的私有字段。
自动属性
- 当属性访问器中不需要任何其他逻辑时,使用自动属性可以更加简洁。
- 本质就是一个字段两个方法。
- 语法:
[访问修饰符]数据类型属性名{
get; set;}
例如:
public int Id {
get; set;}
构造函数
定义
- 提供了创建对象的方式,初始化类数据成员的特殊方法。
- 语 法 :
[访问修饰符]类名([参数列表])
{
初始化 ...
}
特点
- 与类同名。
没有返回值,也不能写void。 - 不能被直接调用,必须通过new 运算符在创建对象时才会自动调用。
- 每个类都必须至少有一个构造函数,若不提供,编译器自动生成一个无参构造函数。
- 如果程序员定义了构造函数,则编译器不会再提供。
this关键字
- 表示当前对象的引用。
- 访问当前类成员时,使用this关键字,可以提高代码的可读性;在没有歧义的情况下,也可以省略。
类结构
访问级别 class类名
{
字段:存储数据
属性:保护字段
构造函数:提供创建对象的方式,初始化类的数据成员
方法:向类的外部提供某种功能
}
Static
静态成员变量
- 使用static关键字修饰的成员变量。
- 静态成员变量属于类,类被加载时初始化,且只有一份。
- 实例成员变量属于对象,在每个对象被创建时初始化,每个对象一份。
- 特点:存在优先于对象,被所有对象所共享,常驻内存。
静态构造函数
- 初始化类的静态数据成员。
- 仅在类被加载时执行一次。
- 不允许使用访问修饰符。
静态构造函数
- 初始化类的静态数据成员。
- 仅在类被加载时执行一次。
- 不允许使用访问修饰符。
静态方法
- 通过引用调用实例方法时,会隐式的传递对象引用,以便在方法内部可以正确访问该对象成员变量。
- 通过类名调用静态方法时,因为没有具体对象,所以在static方法中不能访问实例成员。
静态类
- 使 用static关键字修饰的类。
- 不能实例化,只能包含静态成员。
- 静态类不能被继承,但是静态方法、属性都可以被继承。
适用性
- 利:单独空间存储,所有对象共享,可直接被类名调用。 弊:静态方法中只能访问静态成员,共享数据被多个对象访问会出现并发。
- 适用场合:
1.所有对象需要共享的数据。
2.在没有对象前就要访问成员。
3.工具类适合做静态类(常用,不需要过多数据)。
例子——主函数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Day07
{
internal class Program
{
static void Main2()//具体的老婆
{
//声明Wife类型的 引用
Wife wife01;//声明(栈上)存的是空
//指向Wife类型的对象(实例化Wife类型对象)
wife01 = new Wife();//就是创建了一个wife类型的对象(都是默认值)
wife01.SetName("名字");
wife01.SetAge(18);
Console.WriteLine(wife01.GetName());
Console.WriteLine(wife01.GetAge());
Wife wife02 = wife01;
//wife02 = new Wife();//加上这句话对原来没影响
wife02.SetName("木南");
Console.WriteLine(wife01.GetName());//?
//调用不想写私有属性,公开方法时这样写
Wife wife03 = new Wife();
wife03.Name = "名字2";//执行 Name 的Set代码块
//想同时创建对象 并 赋值
Wife wife04 = new Wife("名字3",19);
//构造函数调用其他的构造函数
Wife wife05 = new Wife("名字3");
}
static void Main3()
{
Wife w01 = new Wife();
w01.Name = "01";
w01.Age = 35;
Wife w02 = new Wife("02", 30);//构造函数:直接可以赋值
Wife[] wifeArray = new Wife[10];
wifeArray[0] = w01;
wifeArray[1] = w02;
wifeArray[2] = new Wife("03", 40);
wifeArray[3] = new Wife("04", 20);
wifeArray[4] = new Wife("05", 25);
//练习1 : 查找年龄最小的老婆
GetWifeByMinimumAge(wifeArray);
}
private static Wife GetWifeByMinimumAge(Wife[] wifes)
{
Wife minWife = wifes[0];
for (int i = 1; i < wifes.Length; i++)
{
if (minWife.Age > wifes[i].Age)//比较的是具体的年纪
minWife = wifes[i];//改变的是栈上面的引用
//minWife.Age = wifes[i].Age;//这样子不行,因为两个人家已经确定的数据不能改变
}
return minWife;
}
}
}
例子——Wife类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Day07
{
/// <summary>
/// 定义老婆类
/// </summary>
class Wife//这里面都是抽象的老婆
{
//-数据成员(公用的地方,放置类)
//--私有的 private,只能大括号里面用
//---字段:存储数据(首字母小写)
private string name;
//不想写私有属性,公开方法的可以下面这样写
//属性:保护字段 本质就是两个方法
public string Name //属性首字母大写
{
//读取时保护
get //本质是下面GetName方法
{
return name; }//如果写成Name(属性内部返回属性,会导致栈溢出)
//写入时保护 value 要设置的数据(希望传入的数据)
set //本质就是下面SetName方法
{
this.name = value; }
}
private string sex;
private int age;
public int Age
{
get
{
return this.age;
}
set //在方法中修改数据
{
if (value <= 19 && value >= 18)
this.age = value;
else
throw new Exception("我不要");
}
}
//构造函数
//构造函数:提供了创建对象的方式,常常用于初始化类的数据成员
//一个类若没有构造函数,那么编译器会自动提供一个无参数构造函数
//一个类若具有构造函数,那么编译器不会提供无参数构造函数
//本质:方法
//特点 : 没有返回值
public Wife() //若不想让这个类创造对象,就让构造函数(类)私有化(private)
{
}
public Wife(string name) : this()
{
//Wife(); 若要调用上面的无参数构造函数
//在构造函数后面写 : this()
this.Name = name;
}
public Wife(string name, int age)//写形参,想同时创建对象 并 赋值
{
this.name = name;//构造函数如果为字字段赋值,属性中的代码块不会执行
//下面的不会执行(构造函数里面给字段还是给属性赋值没有要求,但如果有逻辑判断就要给属性赋值)
//this.Age = age;
this.Age = age;
}
//构造函数:提供了创建对象的方式,常常用于初始化类的数据成员//一个类若没有构造函数,那么编译器会自动提供一个无参数构造函数
//特点 : 没有返回值
int a;
//方法成员
//有“筛选条件”的需求要搭配:私有的类,配公开的方法(写成私有的,就是为了读写,做数据上的验证)
public void SetName(string name)//name是局部变量
{
int a = 1;
Console.WriteLine(this.a);//找的是方法外的那个a
//this 这个对象(引用)
this.name = name; //成员变量//这个参数给数据成员
}
public string GetName()
{
//两者都行有没有this
//return this.name;
return name;
}
public void SetAge(int age)
{
//如果类定义者再有逻辑需求,就可以在方法内部去干
if (age <= 19 && age >= 18)
{
this.age = age; }
else
throw new Exception("不要");
}
public int GetAge()
{
return this.age;
}
}
}
结构 struct
- 定义:用于封装小型相关变量的值类型。与类语法相似, 都可以包含数据成员和方法成员。但结构属于值类型,类
属于引用类型。 - 适用性:
表示点、颜色等轻量级对象。如创建存储1000个点的数组, 如果使用类,将为每个对象分配更多内存,使用结构可以节约资源。
定义结构体
- 使用 struct 关键字定义。
- 除非字段被声明为 const 或 static,否则无法初始化。
- 结构不能继承,但可以实现接口。
构造函数
- 结构总会包含无参数构造函数。
- 构造函数中必须初始化所有字段。