叠甲:
仅供本人自身学习使用,慢慢总结
视频参考---老赵.net
变量类型:
值类型和引用类型
值类型:bool、int、char、decimal、double、enum、struct
引用类型:string、class(类)、数组
1、值类型和引用类型在内存上存储的地方不一样
2、值类型存储在栈中,引用类型存储在堆中
int double string char bool decimal //先声明再赋值后使用
字符串的不可变性
1、当给一个字符串重新赋值时,旧值不会销毁且新的值会在堆中开辟新的空间来存储
2、可以把字符串当成char类型的可读数组
string s="abcdefg"
char[] c =ToCharArray(s)//将字符串转换为char类型数组
c[0]="b" //改变第一个元素的值
s = new string(c)//改后的char数组转换为字符串
stringbuilder类
StringBuilder sb = new StringBuilder();//StringBulider是一个类创建实例
Stopwatch sw = new Stopwatch();//定时器类
sw.Start();//计时开始
for (int i = 0; i < 9999999; i++)
{
sb.Append(i);//append追加累计值
}
sw.Stop();//计时结束
Console.WriteLine(sw.Elapsed);//elapsed运行时间反馈
字符串提供的方法
1、ToCharArray();将字符数组转换为字符串
2、string s = new string(字符数组);将字符数组转换为字符串
3、Length();获得当前字符串中字符的个数
4、ToUpper()将字符转换为大写
ToLower()将字符转换为小写
string s.Equals(string,StringComparison.OrdinalIgnoreCase) 相同类型比较的方法返回bool
StringComparison.OrdinalIgnoreCase这是一个枚举类型调用后文来屏蔽大小写的区别
Console.WriteLine("请输入1");
string s1 = Console.ReadLine();
Console.WriteLine("请输入2");
string s2 = Console.ReadLine();
s1 = s1.ToUpper();//转换为大写
s2 = s2.ToUpper();
string s11 = "";
string s22 = "";
s11 = s1.ToLower();//转换为小写
s22 = s2.ToLower();
if (s1.Equals(s2,StringComparison.OrdinalIgnoreCase))//调用字符串同类型比较的方法
{
Console.WriteLine("相同");
}
else
{
Console.WriteLine("不同");
}
5、Split分割字符串
//分割字符串Split
string s ="a b dfd _ ,,, = + -"
char[] chs ={"+","-",",","=","_"}//声明char类型数组,内的元素为要删除的元素
string[] str = s.Split(chs,StringSplitOptions.RemoveEmptyEntries);//传入要删除的元素,删除后将空一并剔除
string s = "2008-8-8";
char[] c = { '-' };
string[] s1 = s.Split(c,StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine("{0}年{1}月{2}日", s1[0], s1[1], s1[2]);
6、字符串的判断替换内容的方法
str.Contains //判断字符串中有无此字符的方法
str.Replace //替换字符串的方法
string str = "国家关键人物张三";
if (str.Contains("张三"))//判断字符串中有无此字符
{
str = str.Replace("张三", "**");//替换字符串的方法
}
Console.WriteLine(str);
7、SubString截取字符串
在截取时会包含截取的那个索引
string str = "雄关漫道真如铁,而今迈步从头越";
str = str.Substring(2,2);//字符串截取,数一代表开始的位置,数二代表截取长度
Console.WriteLine(str);
8、字符串判断开始与判断结束
str.StartsWith
str.EndsWith
string str = "雄关漫道真如铁,而今迈步从头越";
while (true)
{
string str1 = Console.ReadLine();
if (str.StartsWith(str1))//判断字符串是否以这个字符开始的方法,判断结束同理
{
Console.WriteLine("是的");
}
else
{
Console.WriteLine("不是的");
}
9、判断字符在字符串第一次出现的位置
indexof()
lastindexof()
如果没有返回-1
string str = "测试找找字字符串中中找的第一字个位置";
int x = str.IndexOf('字',6);
Console.WriteLine( x);
//找到字符串中字符第一次出现的位置,返回int数字下标,多时用循环找
int x1 = str.LastIndexOf('字');
Console.WriteLine(x1);
//找到字符串中字符最后一次出现的位置,返回int数字下标,多时用循环找
10、latsindexof与substring应用
string path = @"c:\a\b\c\v\b\d\学习资料";
int index = path.LastIndexOf("\\");
path = path.Substring(index+1);
Console.WriteLine(path);
// lastindexof substring 配合使用
// 先找到最后一个\位置,利用返回的数字截取
11、移除字符串前后的空格
string str0 = " 去前后空格 ";
str0 = str0.Trim();
Console.WriteLine(str0);
string str1 = " 去前面空格 ";
str1 = str1.TrimStart();
Console.WriteLine(str1);
string str2 = " 去后面空格 ";
str2 = str2.TrimEnd();
Console.WriteLine(str2);
12、判断字符串是否为空(null)
string str = null;
if (string.IsNullOrEmpty(str))//判断是否为空
{
Console.WriteLine("yes");
}
else
{
Console.WriteLine("no");
}
13、串联字符数组中的元素join
string[] str = { "将", "字符串", "串联", "拼接" };
string strNew = string.Join( "|",str);
Console.WriteLine(strNew);
运算符与转义字符:
赋值:=
复合赋值:+= -= *= /= %= sum+=age; sum=sum+age;
算数运算:+ - * % ++ --
关系运算:> < >= <= == !=
逻辑运算 &&(逻辑与,表达式两边为真时整体为真) ||(逻辑或,判断一个为真,则结果为真) !(非,如真则假,如假则真)
\t:空格 \n:换行
循环结构:
while循环/do...while循环:
执行过程:程序运行到while处,首先判断while所带的小括号内的循环条件是否成立,如果成立的话,也就是返回一个true,则执行循环体,执行完一遍循环体后,再次回到循环条件进行判断,如果依然成立,则继续执行循环体,如果不成立,则跳出while循环在while循环当中,一般总会有那么一行代码,能够改变循环条件,使之终有一天不再成立如果没有那么一行代码能够改变循环条件,也就是循环条件永远都成立,我们称之这种循环叫做死循环。
最简单的最常用的死循环:
while(true)
while(循环条件)
{
循环体
}
do {循环体}
while{循环条件}
for循环:()
在已知循环条件为数字时推荐用for循环
当遇到某个事要循环一遍,另外一件做N遍时要做for循环的嵌套
语法:
for(表达式1;表还式2;表达式3)
{
循环体;
}
表达式1一般为声明循环变量,记录循环的次数(inti=0;)
表达式2一般为循环条件(i<10)
表达式3一般为改变循环条件的代码,使循环条件终有一天不再成立(i++)。
执行过程:程序首先执行表达式1,声明了一个循环变量用来记录循环的次数,然后执行表达式2,判断循环条件是否成立,如果表达式2返回的结果为true,则执行循环体。当执行完循环体后,执行表达式3,然后执行表达式2继续判断循环条件是否成立如果成立则继续执行循环体,如果不成立,则跳出for循环
定义循环变量
执行循环的条件
改变循环条件的代码使循环终不在成立
条件判断:
switch...case:
执行过程:程序执行到 switch 处,首先将括号中变量或者表达式的值计算出来,然后拿着这个值依次跟每个 case 后面所带的值进行匹配,一旦匹配成功,则执行该 case 所带的代码,执行完成后,遇到 break,跳出 switeh-case 结构,如果,跟每个 case 所带的值都不匹配,就看当前这个 switch-case 结构中是否存在 default,如果有 default,则执行 default 中的语句,如果没有 default,则该 switch-case 结构什么都不做
switch(变量或者表达式的值)
{
case 值 1:要执行的代码;
break;
case 值 2:要执行的代码;
braek;
case 值 2:要执行的代码;
braek;
default:要执行的代码;
break;
}
if-else if:
用来处理多条件区间的判断
continue/break:
打破循环
表达式
三元表达式:
表达式1?表达式2:表达式3;
如果1为true,那么2的值就是整个式子的值
如果1为false,那么3的值就是整个式子的值
注意:2的结果类型与3的结果类型需一致,并且要整个式子的结果类型一致
int max= n1>n2? n1: n2;
console.WriteLine(max)
程序调试
调试:
1.F11逐语句进行调试
2.F10逐过程进行调试
3.断点调试
Main函数为主程序的窗口
异常捕获:
我们在程序中经常会出现各种异常,应该经常使用try-catch来进行异常捕获:
如果try中的代码未出现异常 那么catch中的代码不会执行 反之 try中有异常那么转到catch执行代码
try
{
可能出现异常的代码
}
catch
{
出现异常执行的代码
}
方法(函数):
方法的定义
方法即函数,函数即方法。
方法可以理解为帮我干某件事的人 (方法有返回值,参数),方法的重点为返回值和参数
以下为例:
int x=0
bool b=int.TryParse("123/123abc",out,x);
Console.Write.Line(b);
Console.Write.Line(x);
其中布尔b为返回值
TryParse中的数值即为参数(实参)
方法的结构
函数就是将一堆代码进行重用的一种机制。函数就是一段代码这段代码可能有输入的值(参数),可能会返回值。个函数就像一个专门做这件事的人,我们调用它来做一些事情,它可能需要我们提供一些数据给它,它执行完成后可能会有一些执行结果给我们。要求的数据就叫参数,返回的执行结果就是返回值。
/// <summary>
/// 计算一个整数类型数组的和
/// </summary>
/// <param name="X">代表一组数组</param>
/// <returns>返回这个数组的总和</returns>
public static int RefNums(int[] X)
{
int n = 0;
for (int i = 0; i < X.Length; i++)
{
n = n + X[i];
}
return n;
}
关键字return与关键字void
Rerurn
1.在方法中返回要返回的值
2.结束本次方法
void:不需要返回值
关键字out参数
需要方法返回多个不同数据类型的值时(),考虑使用out参数
/// <summary>
/// 判断用户输入的用户名与密码,并返回结果0或1和登录状态
/// </summary>
/// <param name="n1">接收的用户名</param>
/// <param name="p1">接收的密码</param>
/// <param name="meg">返回的登录状态</param>
/// <param name="b">返回的登陆结果</param>
public static void Login(string n1,string p1,out string meg,out bool b)
{
if (n1 == "admin" && p1 == "123")
{
meg = "登陆成功";
b = true;
return;
}
else if (n1 == "admin")
{
meg = "密码错误";
b = false;
return;
}
else if (p1 == "123")
{
meg = "用户名错误";
b = false;
return;
}
else
{
meg = "未知错误";
b = false;
return;
}
}
static void Main(string[] args)
{
string mesg; //声明string类型接收返回的状态
bool b; //布尔b为返回的结果 0或1
bool c = true; //布尔C控制循环
while (c)
{
Console.WriteLine("请输入用户名");
string name = Console.ReadLine();
Console.WriteLine("请输入密码");
string pwd = Console.ReadLine();
Login(name, pwd, out mesg, out b); //调用Login方法
Console.WriteLine("登陆结果为{0}", b);
Console.WriteLine("登陆状态为{0}", mesg);
if (b == true) //当返回的结果为真时,结束循环
{
c = false;
}
else //当返回的结果为假时,重复循环
{
Console.WriteLine( );
Console.WriteLine("请重新登录");
Console.WriteLine();
}
}
关键字ref参数
ref:
能够将一个变量带入一个方法中进行改变,改变完成后,再将改变后的值带出这个方法
ref参数要求必须在方法外进行赋值,在方法内可以不赋值。
public static void GetMax (ref double x1)
{
x1+=500;
}
static void Main (string[] args)
{
double b=5000;
GetMax(ref b)
Console.WriteLine(b);
}
//输出的值为5500
params可变参数
将实参列表中跟可变参数数组类型一致的元素都处理为这个数组的元素
*必须是形参列表中的最后一个元素,一个参数列表中只能出现一个可变参数,具有唯一性。
public static int GetInput( out int sum, params int[] n1)
{
sum = 0;
int max = 0;
for (int i = 0; i < n1.Length; i++)
{
sum+= n1[i];
if (sum> max)
{
max = n1[i];
}
}
return (max);
}
方法的重载
方法的名称相同但参数不同
如果参数的个数相同那么类型不能相同,参数的类型相同那么个数不能相同,构成方法的重载与返回值的类型没有关系
方法的递归
递归就是在一个方法中调用这个方法,类似于循环,要控制次数保证递归的结束,避免陷入死循环
static void Main(string[] args)
{
FindBox()//Main函数中调用方法
}
pubic static int i=0;//模拟全局变量,在同一个name space或class中都可访问i
public static void FindBox()//定义方法,调用方法实现递归,用i控制循环的次数
{
Console.WriteLine("循环1");
Console.WriteLine( "循环2");
Console.WriteLine("循环3");
i++;
if (i==10)
{
return;
}
FindBox ();
}
常量:
const:
声明赋值后无法改变
const int x = 10;
枚举:
enum:
将枚举声明至namespace下面,实际枚举就是一种变量类型;枚举本质也是存数据
namespace MyAppFirst { public enum Choose { dog,//值1 cat//值2 //...后续值 } internal class Program { static void Main(string[] args) { Choose x= Choose.dog; Choose y= Choose.cat; }
枚举就是一个变量类型,只是枚举声明、赋值、使用的方式跟那些普通的变量类型不一样
我们可以将一个枚举类型的变量跟int类型和string类型相互转换。
枚举类型默认是跟int类型相互兼容的,所以可以通过强制类型转换的语法互相转换
当转换一个枚举中没有的值的时候,不会抛异常,而是直接将数字显示出来。
枚举同样也可以跟string类型互相转换,如果将枚举类型转换成string类型,则直接调用Tostring().
如果将字符串转换成枚举类型则需要下面这样一行代码:
(要转换的枚举类型)Enum.Parse(typeof(要转换的枚举类型),"要转换的字符串")
示例:
namespace MyAppFirst
{
public enum QQState
{
OnLine,
OffLine,
Leave,
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine( "状态:0--OnLine,1--OffLine,2--Leave" );
string xx=Console.ReadLine();
switch (xx)
{
case "0":
QQState n1 = (QQState)Enum.Parse(typeof(QQState), xx);
Console.WriteLine("状态为{0}", n1);
break;
case "1":
QQState n2 = (QQState)Enum.Parse(typeof(QQState), xx);
Console.WriteLine("状态为{0}", n2);
break;
case "2":
QQState n3 = (QQState)Enum.Parse(typeof(QQState), xx);
Console.WriteLine("状态为{0}", n3);
break;
}
如果转换的字符串是数字,则就算枚举中没有,也会不会抛异常。
如果转换的字符串是文本,如果枚举中没有,则会抛出异常。
所有的类型都能够转换成string类型,调用Tostring()
string y = "A";
season c= (season ) Enum.Parse(typeof(season), y);
Console.WriteLine(c);
结构和数组:
struct
一次性声明多个不同类型的
变量。
//public struct 结构名
//{
// 成员;//字段(声明前加下划线)
//}
public struct Person
{
public string _name;
public int _age;
public Gender _gender;
}
public enum Gender
{
男,
女
}
Person A;
A ._age = 23;
A._gender = Gender.男;
A._name = "DIV";
Person B;
B._age = 78;
B._gender = Gender.女;
B._name = "KISO";
数组:
一次性存储相同类型的变量
int [] nums=new int[10]; //数组类型[] 定义数组名=new 数组类型[数组长度];
int[] bb = new int[10];
for (int i = 0; i < bb.Length; i++)
{
bb[i] = i + 1; //赋值
}
for (int i = 0; i < bb.Length; i++)
{
Console.WriteLine(bb[i]); //打印i的值
}
当你写了上面这样一样代码之后,就在内存中开辟了连续的10块空间,我们管每一个块称之为这个数组的元素。
如果你想要访问到数组中某一块元素,需要通过这个元素的索引(下标)去访问,索引的开始为0,最后为(数组的长度-1)。
数组元素的交换:
string[] name = { "a", "b", "c", "d", "e", "f" };
//a,b,c,d,e,f 索引为0,1,2,3,4,5
/* 第一次交换为 a--f==0--5
* 第二次交换为 b--e==1--4
* 第三次交换为 c--d==2--3
* 循环的进行交换
* 交换的次数== name.Lengh/2
* 其中 前值可用name[i]表示;后值可用name.Lengh-1-[i]表示
*/
for (int i = 0; i < name.Length / 2; i++) //循环的次数为 name.Lengh/2
{
string temp = name[i]; //声明中间变量
name[i] = name[name.Length - 1 - i]; //前值与后值进行交换
name[name.Length - 1 - i] = temp;
}
for (int i = 0; i < name.Length; i++)
{
Console.WriteLine(name[i]);
}
冒泡排序:
namespace test
{
public class paixu
{
static void Main(string[] args)
{
int[] number = { 0, 3, 2, 5, 1, 4, 9, 7, 6, 8 };//声明数组
for (int i = 0; i < number.Length-1; i++)//循环次数为数组长度-1
{
for (int j = 0; j <number. Length-1-i; j++)//循环交换
{
if (number[j] <number[j+1])//判断大小
{
int TEMP = number[j];
number[j] = number[j + 1];
number[j + 1] = TEMP;
}
}
}
for (int i = 0; i <number .Length; i++)
{
Console.WriteLine(number[i]);
}
}
}
}
Array.Sort(number);//对数组升序排序的方法(单独调用会升序排序)
Array.Reverse(number);//对数组中元素对调交换的方法
//两种组合使用可对数组中的元素进行降序排序
for (int i = 0; i < number.Length; i++)
{
Console.WriteLine(number[i]);
}
面向对象
Fields:字段
Methods:方法
Properties:属性
定义:我们在代码中描述一个对象,就是描述对象的属性和方法,定义对象要精确描述,要看得见摸得着
类(class)
类(class):把具有相同属性和相同方法的对象进行进一步的封装,其中我们抽象出来的概念称之为类,类相当于模板,确定了属性具有的属性和方法
public class Person//声明一个类包含人类的特征
{
public string _name;
public string _age;
public int _height;
public void testMethod
{
Console.WriteLine("{0}今年{1}岁了,身高{2}厘米",this._name,this._age,this._height);
}
}
public class test
{
static void Main(string[]args)
{
Person zhangsan =new Person();//创建对象
zhangsan._name="张三";
zhangsan._age="22";
zhangsan._height=180;
testMethod();//调用类的方法
}
}
属性
属性的本质就是保护字段(避免错误的赋值和取值并对其限定),包含两个方法get取值与set赋值
internal class properties属性
{
private string _name;
public string Name
{
get { return _name; }//取值
set { _name = value;}//赋值
}
访问修饰符
Public:公开的
Private:私有的
Protected:受保护的,只能在当前类和这个类的子类中访问
Internal:只能在当前程序集中访问,在同一个项目中和public权限一致
Protected Internal:受保护的内部,如果是继承关系,不管是不是在同一程序集中都可以访问;如果不是继承关系只能在同一程序集中访问
1.修饰类的只能是public和internal
2.子类的访问权限不能高于父类
继承
继承的特性
父类----子类 /基类---派生类
1、把几个类中重复的内容提取出来创建一个新的父类就是继承
2、子类只能继承公有字段,私有的无法继承
3、子类不能继承父类的构造函数,但是子类会默认调用父类无参数的构造函数,创建父类对象,让子类可以使用父类中的成员
在父类中创建有参的构造函数,无参会被覆盖,此时继承的子类会无法调用显示报错解决方法如下:
1)、在父类中重新声明一个无参的构造函数
2)、在子类显式的调用父类的构造函数使用关键字:base()
4、单根性:一个子类只能继承于一个父类
5、传递性:子类继承于父类之后,这个子类可以被其它子类继承并成为它的父类
internal class 继承的学习
{
public static void Main(string[] args)
{
programmer zspro = new programmer("张三", 25, '男', 5);
zspro.Anima();
zspro.skill();
camus camusMethod = new camus("加缪", 50, '男', 20);
camusMethod.xiezuo();
camusMethod.Anima();
}
}
//继承:
//程序员:张三,性别男,年龄22岁,码龄5年,技能:熟练编程
//作家:加缪,性别男,年龄50,写作时间:20,技能:荒诞
//皇帝:赵匡胤,性别男,年龄35,起义时间960年,技能:黄袍加身
public class person//创建父类person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
public person(string name, int age, char gender)//父类的有参构造函数,包含子类共有的name,age,gender
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
public void Anima()//父类的方法,子类共有
{
Console.WriteLine("这是人类生命的方法");
}
}
public class programmer : person
{
public programmer(string name, int age, char gender, int Maling) : base(name, age, gender)//子类的构造函数
{
this.Maling = Maling;
}
private int _maling;
public int Maling
{
get { return _maling; }
set { _maling = value; }
}
public void skill()
{
Console.WriteLine("我是{0},我的年龄是{1},性别是{2},码龄为{3},我会熟练编程", this.Name, this.Age, this.Gender, this.Maling);
}
}
public class camus : person
{
private int _writing;
public int Writing
{
get { return _writing; }
set { _writing = value; }
}
public camus(string name, int age, char gender, int writing) : base(name, age, gender)
{
this.Writing = writing;
}
public void xiezuo()
{
Console.WriteLine("我是{0},我的年龄是{1},性别是{2},码龄为{3},我会熟练编程", this.Name, this.Age, this.Gender, this.Writing);
);
}
}
}
静态与非静态
特点
1.在非静态类中,既可以有实例(非静态)成员,也可以有静态成员
2.在非静态类中,调用实例(非静态)成员的时候需要先创建实例化使用对象名.实例(非静态)成员();
3.在非静态类中,调用静态成员的时候需要用类名.静态成员名;
4.在静态类中只允许创建静态成员,且静态类不允许被实例化
总结:静态成员必须用类去调用,非静态必须用实例化对象名去调用,上述包括:字段、属性、方法。而且静态方法中只允许访问静态成员,非静态不可访问;非静态方法中则两中成员都可以可以访问。
使用
1、如果你想你要创建的类当作"工具类”去使用,这时候可以考虑将这个类创建为静态的
2、静态类在整个项目中资源共享。只有程序全部结束后静态类才会释放资源
.Net中的资源释放,引入了GC(garbage collection 垃圾回收器)
构造函数
构造函数定义
构造方法用来创建对象,并且在构造函数中对对象进行初始化。
构造函数是特殊的方法,对初始化进行依次的赋值
1.构造函数没有返回值,且不能写void
2.构造函数的名称必须与类名一致
3.声明一个类中,默认会生成一个无参数的构造函数,但当主动声明新的构造函数时,这个无参构造函数会被覆盖掉
New关键字
创建对象的作用:
1、在内存中开辟空间
2、在开辟的空间中创建对象
3、调用对象的构造函数进行初始化
4、在类中可以隐藏从父类继承过来的同名成员,隐藏的后果就是子类调用不到父类的成员
This关键字
作用:
1.代表当前类的对象
2.在类当中显示调用本类的构造函数(:this)
析构函数
在程序结束时才会执行,目的帮助程序释放资源
里氏转换
定义:
1、子类可以赋值给父类
2、如果父类中装的是子类的对象,那么可以将这个父类强转为子类对象
用as强制转换
person p = new Showmaker("li", 3, '8');//父类创建子类对象
Showmaker nn = p as Showmaker;//将父类强转为子类的对象
nn.Anima();//这个子类可以调用父类的anima方法
nn.show();//这个子类也可以调用子类的自己的show方法
用is判断转换
person p = new camus("1", 1, '1', 1);//父类创建子类对象
if (p is camus)//用is尝试将父类转换为camus子类对象
{
camus zz = (camus)p;//如果可以就转换
zz.pSayHello();//调用父类psayhello方法
zz.jSayHello();//调用子类jsayhello方法
}
else//否则转换失败
{
Console.WriteLine("转换失败");
}
用于转换的关键字 is/as
is:表示类型转换,转换成功返回ture,失败返回false
as:表示类型转换,转换成功返回类型的对象,失败返回null
as 类型转换失败时值为null不抛出异常
但强制转换如果转换失败会抛出异常所以我们要添加异常处理
is : 检查一个对象是否兼容于其他指定的类型,并返回一个Bool值,永远不会抛出异常
命名空间(Name Space)
1、可以看作类的文件夹
2、在项目中想用其他项目的类有两步:1.解决方案资源管理器右键引用添加 2.代码中using命名空间
3.alt+shift+F10 快捷键在visual studio中快捷引用namespace
集合
ArrayList
1.可添加的元素类型不限,整个集合长度可变,但是取数据时数据类型都为object
2. 每次集合中实际包含元素的个数(count)超过了可以包含元素的个数(capacity)的时候
集合就会向内存中开辟多一倍的空间,保证集合的长度够用
3.会发生拆装箱
ArrayList list = new ArrayList();
//添加单个元素
list.Add(800);
list.Add("C#");
list.Add("张三");
//添加集合元素
list.AddRange(new int[] { 1, 2, 3, 4 });
//集合中实际包含元素的个数
int n=list.Count;
//集合中能够包含元素的个数
int n1 = list.Capacity;
//清除集合中的所有元素
list.Clear();
list.Remove("C#");//删除指定的元素
list.RemoveAt(3);//根据索引删除元素
list.RemoveRange(0, 3);//根据索引删除范围内的元素
list.Insert(0, "插入的");//在指定索引插入单个值
//在指定位置插入集合值
list.InsertRange(1, new string[] { "张三", "李四" });
bool b = list.Contains(1); //判断是否包含指定的元素
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
}
}
//长度为10的集合,要求里面随机的存放10个数字(0-9)
//要求所有数字不能重复
ArrayList n = new ArrayList();
Random r = new Random();
for (int i = 0; i < 10; i++)
{
int r1 = r.Next(0, 10);
//判断集合中没有这个随机数
if (!n.Contains(r1))
{
n.Add(r1);
}
//如果有这个随机数,循环次数会减少,所以i--将次数加1
else
{
i--;
}
}
for (int i = 0; i < n.Count; i++)
{
Console.WriteLine(n[i]);
}
}
键值对集合Hashtable
此集合中的所有方法都与键有关,可以理解为索引
Hashtable X = new Hashtable();//键值对集合
X.Add(1, "张三");
X.Add(2, true);
X.Add(false, "错误");
X[3] = "新添加的";
foreach (var item in X.Keys)
{
Console.WriteLine("集合中键是---{0},值是{1}", item, X[item]);
}
HASHTABLE的练习
internal class 繁简转换
{
//声明常量
private const string jian = "123456789";
private const string fan = "一二三四五六七八九";
static void Main(string[] args)
{
Hashtable ht = new Hashtable();//创建hashtable对象
for (int i = 0; i <jian.Length ; i++)//循环给键和值赋对应的值,长度统一
{
ht.Add(jian[i], fan[i]);
}
Console.WriteLine("请输入数字");
string test = Console.ReadLine();
for (int i = 0; i <test.Length ; i++)
{
if (ht.ContainsKey(test[i]))//用containskey判断这个键值对集合中有没有test[i]的值
{
Console.Write(ht[test[i]]);//ht[test[i]]代表这个键对应的值
}
else//如果这个集合中不包含则输出原值
{
Console.Write(test[i]);
}
}
}
}
List<T>泛型集合
1.泛型集合在创建对象时需声明数据类型,而且其中的每个元素必须与类型对应
2.泛型集合可以转换为与集合数据类型对应的数组
3. 确定了集合中元素的数据类型,不会发生拆装箱
static void Main(string[] args)
{
//创建泛型集合对象
List<int> list = new List<int>();
list.Add(30);
list.AddRange(new int[] { 1, 2, 3, 4, 5, 6 });//泛型集合的方法
list.AddRange(list);
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
int[] nums= list.ToArray();//泛型集合转换为对应集合类型的数组
char[] chs = new char[] { 'c', 'b', 'a' };//数组转换为泛型集合
List<char> listchs= chs.ToList();
for (int i = 0; i < listchs.Count; i++)
{
Console.WriteLine(listchs[i]);
}
string[] str = new string[] { "自", "是", "人", "生", "长", "恨", "水", "长", "东" };
List<string> liststr = str.ToList();
for (int i = 0; i < liststr.Count; i++)
{
Console.WriteLine(liststr[i]);
}
string[] str2 = liststr.ToArray();
for (int i = 0; i < str.Length; i++)
{
Console.Write(str2[i]);
}
Console.ReadKey();
}
装箱与拆箱
1.装箱:将值类型转换为引用类型
2.拆箱:将引用类型转换为值类型
3.判断两种类型有没有装箱或拆箱,需要看这两种类型是否为继承关系,有继承关系只是有可能会拆装箱
4.装箱或拆箱都会影响系统性能,在代码中应该尽量避免
Dictionary字典集合
1. 不会发生拆装箱
集合的三个练习题
//将一个数组中的奇数放到一个集合,偶数放到一个集合
//最终将这两个集合合并为一个,奇数显示在左,偶数显示在右
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//声明一个int数组
List<int> listj = new List<int>();//创建奇数泛型集合
List<int> listo = new List<int>(); //创建偶数泛型集合
for (int i = 0; i < nums.Length; i++)//循环遍历数组
{
if (nums[i] % 2 == 0)//判断循环到的元素是否为偶数
{
listo.Add(nums[i]);//是 将这个元素添加到偶数集合
}
else
{
listj.Add(nums[i]);//否 那么为奇数将这个元素添加到奇数集合
}
}
listj.AddRange(listo);//将偶数泛型集合添加到奇数泛型集合
foreach (int item in listj)//遍历奇数泛型集合输出内的元素
{
Console.Write(item + " ");
}
//提示用户输入一个字符串,通过foreach循环将输入的字符串赋值给另一个字符数组
Console.WriteLine("请输入一个字符串");
string str = Console.ReadLine();
char[] chs = new char[str.Length];//声明一个char数组长度与输入的字符串一致
int n = 0;
foreach (var item in str)//循环这个字符串
{
chs[n] = item;//chs[n]代表元素的索引,item为str中的每个元素
n++;//控制n增长代表下标,但是长度始终与字符串长度一致
}
foreach (var item in chs)//遍历char数组输出元素
{
Console.WriteLine(item);
}
//统计 welcome to china 中每个字符出现的次数,不考虑大小写
string input = "welcome to china";
Dictionary<char, int> dic = new Dictionary<char, int>();
//字符作为键,值为出现的次数
for (int i = 0; i < input.Length; i++)
{
if (input[i] == ' ')
{
continue;
}
//如果dic已经包含当前循环到的这个键
if (dic.ContainsKey(input[i]))
{
//值再次加一
dic[input[i]]++;
}
else
{
dic[input[i]] = 1;
}
}
foreach (KeyValuePair<char, int> item in dic)
{
Console.WriteLine("{0}----{1}", item.Key, item.Value);
}
文件操作
Path类
对文件路径的操作
static void Main(string[] args)
{
// path类为静态类
string str = @"D:\1.工作文件存放\3.中转仓方案资料\01.仓库资料\WCS流程图.png";
//获得文件名字
Console.WriteLine(Path.GetFileName(str));
//获得文件名称不包含拓展名
Console.WriteLine(Path.GetFileNameWithoutExtension(str));
//获得文件的拓展名
Console.WriteLine(Path.GetExtension(str));
//获得文件所在的文件夹的名称
Console.WriteLine(Path.GetDirectoryName(str));
//获得文件所在的全路径
Console.WriteLine(Path.GetFullPath(str));
//将文件路径连接到一起(连接两个字符串为路径)
Console.WriteLine(Path.Combine(@"c:\a\", "文件.txt"));
}
File类
对文件的操作
String[] S = File.ReadAllLines(@"C:\Users\数据中心064\Desktop\new.txt", Encoding.Default);//读取以字符串形式的文件,返回字符串数组
foreach (String item in S)//用foreach循环遍历这个字符串数组
{
Console.WriteLine(item);
}
string str =File.ReadAllText(@"C:\Users\数据中心064\Desktop\new.txt", Encoding.Default);//读取文本文件将所有内容返回为一个字符串
Console.WriteLine(str);
byte[]bb= File.ReadAllBytes(@"C:\Users\数据中心064\Desktop\new.txt");//以字节的形式读取文件,文件类型不限
string ss = Encoding.Default.GetString(bb);//encoding静态类,Default默认字符编码方式
Console.WriteLine( ss);
FlieStream/StreamReader/StreamWriter文件流
1.FlieStream操作字节,代表可以操作所有文件
2.using语句可以避免自己主动写程序来关闭文件流和释放资源
//使用FlieStream读取数据
//创建FS对象,构造函数中参数1为文件路径,
//参数2FlieMode(枚举类型)为对这个文件进行的操作,
//参数3FlieAccess(枚举)为对文件内容的操作
FileStream fsRead = new FileStream(@"C:\Users\数据中心064\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Read);
byte[] buffer = new byte[1024 * 1024 * 5];
//read返回本次实际读取到的有效字节数
int RE = fsRead.Read(buffer, 0, buffer.Length);
//将字节数组中每一个元素按照指定的编码格式解码成字符串
string str = Encoding.Default.GetString(buffer);
//用完文件流关闭流占用的资源
fsRead.Close();
//释放占用的资源
fsRead.Dispose();
//打印读取的数据
Console.WriteLine(str);
Console.WriteLine(RE);
//使用FlieStream读取数据
//using语句可以避免自己主动写程序来关闭文件流和释放资源
using (FileStream fswrite = new FileStream(@"C:\Users\数据中心064\Desktop\测试文件流.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
string strW = "这是测试FlieStream读取文件内容是否会覆盖的一条字符串";
byte[] bb = Encoding.Default.GetBytes(strW);
fswrite.Write(bb, 0, bb.Length);
Console.WriteLine("写入成功");
}
复制多媒体文件
FlieStream/StreamReader/StreamWriter文件流
1.FlieStream操作字节,代表可以操作所有文件
2.using语句可以避免自己主动写程序来关闭文件流和释放资源
//使用FlieStream读取数据
//创建FS对象,构造函数中参数1为文件路径,
//参数2FlieMode(枚举类型)为对这个文件进行的操作,
//参数3FlieAccess(枚举)为对文件内容的操作
FileStream fsRead = new FileStream(@"C:\Users\数据中心064\Desktop\new.txt", FileMode.OpenOrCreate, FileAccess.Read);
byte[] buffer = new byte[1024 * 1024 * 5];
//read返回本次实际读取到的有效字节数
int RE = fsRead.Read(buffer, 0, buffer.Length);
//将字节数组中每一个元素按照指定的编码格式解码成字符串
string str = Encoding.Default.GetString(buffer);
//用完文件流关闭流占用的资源
fsRead.Close();
//释放占用的资源
fsRead.Dispose();
//打印读取的数据
Console.WriteLine(str);
Console.WriteLine(RE);
//使用FlieStream读取数据
//using语句可以避免自己主动写程序来关闭文件流和释放资源
using (FileStream fswrite = new FileStream(@"C:\Users\数据中心064\Desktop\测试文件流.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
string strW = "这是测试FlieStream读取文件内容是否会覆盖的一条字符串";
byte[] bb = Encoding.Default.GetBytes(strW);
fswrite.Write(bb, 0, bb.Length);
Console.WriteLine("写入成功");
}
2.StreamReader,StreamWriter操作字符
2.StreamReader,StreamWriter操作字符
编码
将字符串以怎么样的形式转换为二进制并保存
ASCLL128、ACSLL256、GB2312简体字、Big5、unicode、UTF-8
乱码就是保存这个文件的编码与打开这个文件的编码不一致
多态
让一个对象表现出多种状态(类型)
减少代码量,屏蔽各个子类间的差异,写出通用的代码
虚方法
步骤:
1.将父类的方法标记为虚方法,使用关键字virtual,这个方法可以被子类重写,子类方法使用override
2.如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态
抽象类
关键字:abstract
1.如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。
2.标记在类和方法前代表是抽象的,抽象方法没有方法体
3.当父类方法不知道改如何实现时,可以考虑将父类写为抽象类,方法写为抽象方法
1.抽象成员必须标记为abstract,并且不能有任何实现,抽象成员必须在抽象类中。
2.子类继承抽象类后,必须把父类中的所有抽象成员都重写。(除非子类也是抽象类,则可以不重写)
3.抽象成员的访问修饰符不能是private
4.在抽象类中可以包含实例成员。
5.抽象类的实例成员不被子类实现
6.抽象类是有构造函数的。虽然不能被实例化。
7.如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数
8.如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。
抽象类练习题:
用多态的概念模拟硬盘、u盘、MP3插到电脑进行数据的读写
namespace _11.多态
{
internal class 抽象类电脑练习
{
static void Main(string[] args)
{
//问题:用多态模拟硬盘、u盘、MP3插到电脑上进行数据的读写
//1.创建父类---电子设备,读写两种方法
//2.创建子类---硬盘、U盘、MP3,重写读写方法
//3.创建类---电脑,电脑调用到电子设备的读写方法,将父类作为参数传入
//4.调用电脑的读写方法
Device dvi = new disk(); //new MP3();//new Upan();//创建父类对象 内部为子类参数
computer c1 = new computer();//创建“电脑”类对象
c1.Dvi = dvi;//给电脑类的属性赋值,值为创建的u盘子类
c1.CPUread();
c1.CPUwirte();
}
}
//父类---电子设备
public abstract class Device
{
public abstract void read();
public abstract void wirte();
}
//子类---硬盘
public class disk : Device
{
public override void read()
{
Console.WriteLine("硬盘读取");
}
public override void wirte()
{
Console.WriteLine("硬盘写入");
}
}
//子类---u盘
public class Upan : Device
{
public override void read()
{
Console.WriteLine("U盘写入");
}
public override void wirte()
{
Console.WriteLine("U盘读取");
}
}
//子类---MP3
public class MP3 : Device
{
public override void read()
{
Console.WriteLine("mp3写入");
}
public override void wirte()
{
Console.WriteLine("MP3读取");
}
}
//类---电脑
public class computer
{
//1.这是用字段与属性传参的写法
private Device _dvi;
public Device Dvi { get { return _dvi; } set { _dvi = value; } }
public void CPUread()
{
Dvi.read();
}
public void CPUwirte()
{
Dvi.wirte();
}
//2.这是往方法中传参的写法
//public void CPUread(Device Dvi)
//{
// Dvi.read();
//}
//public void CPUwirte(Device Dvi)
//{
// Dvi.wirte();
//}
//3.这是往构造函数中传参的写法
//public computer(Device dvi)
//{
// this.Dvi = dvi;
//}
//public void CPUread()
//{
// Dvi.read();
//}
//public void CPUwirte()
//{
// Dvi.wirte();
//}
}
}
接口
设计模式
帮助我们在开发中遇到的问题,常用有23种设计模式
2425

被折叠的 条评论
为什么被折叠?



