解决方案:一个解决方案可以有多个项目,这些项目通过解决方案连接在一起
引用:是这个项目的框架也是工具,当框架不足可以通过鼠标右键添加新的框架
Program.cs:程序入口文件
class Progress{
static void Main(string[] args){
}
}
其中static void Main(string[] args){}一个项目中只能有一个入口
命名空间
1.分类:系统命名空间和自定义命名空间
2.命名空间可以重名但都是在同一个命名空间
3.关键字:namespace
4.命名空间和类的关系:命名空间包含类
同一命名空间不能有相同名字的类
定义多个相同名字的类可以用不同名字的命名空间进行保存
namespace XiangMu{
class Progress{
static void Main(string[] args){
}
}
class XiangMu{
}
}
namespace xiangMu{
class XiangMu{
}
}
注释
定义:解释说明
在要注释的代码前一行进行注释
//单行注释
/* */多行注释
///方法注释
#region 解释内容:开头 #endregion :结尾
#region
internal class Program
{
#region
static void Main(string[] args)
{
int a = Convert.ToInt32(Console.ReadLine());
int b = a;
int result = 0;
while (a != 0)
{
int n = a % 10;
result *= 10;
result += n;
a /= 10;
}
if (result == b)
{
Console.WriteLine("Yes");
}
else
{
Console.WriteLine("No");
}
Console.WriteLine(result);
//Console.ReadKey();
//Console.Read();在控制台读取一个字符
//在使用char数据类型时需要显示转换,使用int类型时可以直接读取但单个字母会自动转换为整数
//char a =(char)Console.Read();
// \u开头是 unicode编码 每个\u开头单指一个字
//Conaole.ReadLine();在控制台读取一行字符
//Console.ReadKey();
int s = Console.Read();
Console.WriteLine(s);
Console.ReadKey();
}
#endregion
}
#endregion
标识符
就是变量名、类名、方法名、函数名、命名空间名等
数据类型
分为:值类型和引用类型
值类型:整数类型、浮点型、字符型、布尔类型、struct(结构)、enum(枚举)
引用类型:字符串、类、接口、数组、集合、委托
整数类型
byte 无符号整数 8
sbyte 有符号整数 8
int 有符号整数 32
uint 无符号整数 32
short 有符号整数 16
ushort 无符号整数 16
loog 有符号整数 64
uloog 无符号整数 64
有符号整数:有负数的整数
无符号整数:从0开始的正整数
后面的数字代表宽度也是占的容量
object是所有类型的基类它保存的是引用对像的32(4字节)地址
bool 布尔类型 true或false 宽度:8 bool a=true; !a则是false
float 单精度浮点型 精确到小数点后6位 f或F后缀
double 双精度浮点型 精确到小数点后15位 d或D后缀
char 单字符类型 英文转整数对应ACSLL编码 char a='a'; int b=a;输出b=97 中文对应Unicode编码char c='\u5F20'输出”张”这个字
decimal 具有高精度的小数数值比float和double精度更高 m或M后缀
class Program
{
//一个C#程序中只能有一个Main()方法,也是程序入口点,执行起来总是要从Main()开始
static void Main(string[] args)
{
//"\"转义符\n换行\b退行\f换页
//@会使转义符无效
string a = @"\n五天";
//多行字符串
string b = @"33e5
5rd";//输出后占2行
string c = "\\\\\\\n";
string d = @"\\\\\\\n";
//Console 控制台
//WriteLine 写一行
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
//Console.ReadKey()起到了暂停的作用
//第二个作用,等待我们输入一个按钮,它会进行关闭
byte a2 = 3;//0-255
sbyte a3 = -4;
Console.WriteLine(a2);
Console.WriteLine(a3);
object a4 = 5;
//单精度浮点型精确到小数点后6位
float a6 = 1.3333333333F;
//双精度浮点型精确到小数点后15位
double a7 = 1.44444444444444444444444444444444444444444D;
double a8 = 1.44d;
decimal a5 = 1.222222222222222222222222222222222222222222222222222222M;
decimal b6 = 1.3333m;
Console.WriteLine(a4);
Console.WriteLine(a6);
Console.WriteLine(a7);
Console.WriteLine(a8);
Console.WriteLine(a5);
Console.WriteLine(b6);
//运用到s+a时输出是100
//英文对应ACSLL编码
char s = 'a';
Console.WriteLine(s+a2);
char s1 = '你';
Console.WriteLine(s1);
//中文对应Unicode编码
char s2 = '\u5F20';
Console.WriteLine(s2);
DateTime date = DateTime.Now;
Console.WriteLine(date);
Console.ReadKey();
}
}
转义符
"\":转义符
使用方法:\n 换行 \t 横向跳到下一指标位置 \b 退格 \r 删除该行\r前的内容
Console.ReadKey();暂停程序运行,点击任以键退出
Console.WriteLine();和Console.Write('\n');效果一样都只有换行
占位符
string a ="小明";
Console.WriteLine(“你好,{0}”,a);
输出的是:你好,小明
驼峰法
小驼峰:用于变量名、对象名;int intName;变量名首字母小写其他首字母大写
大驼峰:用于方法、类名、属性名;class ProgressName;类名首字母都大写
常量名全都大写 const int CONST_INT_NAME=10;并且必须在定义时进行赋值
变量
变量在相同的作用域不允许有相同的变量名
未赋值的变量不允许直接输出(可以在后续代码中 变量名=值;进行赋值)
变量只能保存最新的值
可以同时定义多个变量
格式:数据类型 变量名 = 值;
单个=号只有赋值的作用
//变量 常量
//变量不允许在相同作用域出现相同的变量名
//未赋值的变量不能直接输出
//数据类型 变量名
int a;
a = 1;
//a被替换成新的值
//变量只能保存最新的数据内容
a = 10;
//可以同时定义多个变量
//局部变量需要赋值之后才能使用
//int b, c, d;
//Console.WriteLine(b);
常量
注意:代码结尾是";"英文引号
存储不变的数据
关键词:const
分为值类型常量和字符串类型常量和const和readonly。都能定义为方法中的常量
const是默认静态的,且只能在字段中定义。
readonly可以在字段中赋值或在构造函数中赋值,readonly并非默认静态的。
readonly在构造函数中赋值意思是,可以先定义readonly int a;字段,然后在在构造函数中赋值。
值类型常量和字符串类型常量:
在定义一个变量时只时引用这个变量不改变存储位置还是原来的值
其实就是像一个常量
const:
格式:const 数据类型 常量名 = 值;
常量名全部大写
常量必须在定义时赋值
后续代码如有更改常量会报错
//常量
//存储不变的数据
//分为:值类型常量和字符串类型常量和const和readOnly
//值类型常量
//不改变变量的存储位置时类似与常量
//也就是不改变值时
int intNumber10 = 10;//10进制
intNumber10 = 10;
int intNumber1 = 0X20;//16进制
int intNumber2 = 012;//八进制
float floatNumber10 = 10.1f;
long longNumber1 = 100L;
uint uitNumber1 = 100u;
char charNumber11 = 'a';//英文
char charNumber21 = '中';//中文
char charNumber41 = '\u058F';//Unicode编码
string stringNumber11 = "abc";//字符串常量
Console.WriteLine(intNumber10);
//const常量
//const表示的常量在定义时必须赋值
//const int intNumber ;
//const表示的常量名字要全大写
const int CONST_INT_NUMBER = 50;
//const常量使用场景比如特殊的数字和特殊的符号
const double CONST_DOUBLE = 3.1415926;
Console.WriteLine(CONST_DOUBLE * 10 * 10);
Console.ReadKey();
类型转换
分为:隐式转换、显示转换、字符串转值(Parse和TryParse)、值转字符串(ToString())、强制转换(Convert不常用)
//类型转换
//有符号类型与无符号类型之间进行转换需要显示转换
//隐式转换
//小转大
sbyte sbyteNumber = 10;
short shortNumber = sbyteNumber;
int intNumber = shortNumber;
long longNumber = intNumber;
//整数转小数
float floatNumber = longNumber;
double doubleNumber = longNumber;
double doubleNumber1 = floatNumber;
decimal decimalNumber = longNumber;
//GetType().ToString()前面的是显示数据类型后面的是转为字符串类型
string stringNumber =floatNumber.GetType().ToString();
Console.WriteLine(stringNumber);
//输出
Console.WriteLine(shortNumber);
Console.WriteLine(shortNumber.GetType().ToString());//显示数据类型和宽度
Console.WriteLine(intNumber);
Console.WriteLine(longNumber);
Console.WriteLine(floatNumber);
Console.WriteLine(doubleNumber);
Console.WriteLine(doubleNumber1);
Console.WriteLine(decimalNumber);
//显示转换
//大转小
//范围大的向范围小的转时可能会丢失数据
long longNumber1 = 23;
int intNumber1 =(int)longNumber1;
short shortNumber1 = (short)intNumber1;
sbyte sbyteNumber1 = (sbyte)shortNumber1;
//有符号类型转无符号类型
ulong ulongNumber =(ulong)longNumber1;
uint uintNumber = (uint)longNumber1;
//decimal转double或float
decimal decimalNumber1 = 1.4444444444m;
double doubleNumber2 = (double)decimalNumber1;
float floatNumber2 =(float)decimalNumber1;
//double或float转decimal
decimal decimalNumber2 = (decimal)doubleNumber2;
decimal decimalNumber3 = (decimal)floatNumber2;
//输出
Console.WriteLine(intNumber1);
Console.WriteLine(shortNumber1 );
Console.WriteLine(sbyteNumber1 );
Console.WriteLine(ulongNumber);
Console.WriteLine(uintNumber);
Console.WriteLine(doubleNumber2);
Console.WriteLine(floatNumber2);
Console.WriteLine(decimalNumber2);
Console.WriteLine(decimalNumber3);
//字符串转值
//Parse转换
string strNumber2 = "123";
int intNumber6 = int.Parse(strNumber2);
Console.WriteLine(intNumber6);
//TryParse转换
string strNumber3= "123a";
//定义输出参数,用于接收结果
int result;
bool boolNumber = int.TryParse(strNumber3, out result);
Console.WriteLine(result);
Console.WriteLine(boolNumber ? "转换成功" : "转换失败");
//值转字符串
//ToString()
//基于所有类型基类的方法
string strNumber4 = intNumber.ToString();
string strNumber5 = decimalNumber1.ToString();
Console.WriteLine(strNumber4);
Console.WriteLine(strNumber5);
Console.WriteLine(strNumber4.GetType().ToString());
Console.ReadKey();
运算符
+、-、*、/、%
加、减、乘、除、取余
++、--
加加、减减;也就是加1减1
int a=1;
int b = a++;在这里++在后面,先赋值给b在自加1所以在运行完时a才等于2
int c = ++a;在这里++在前面,先自加1在赋值给b所以在赋值前a等于2
//大区间于小区间求和结果是大区间
//运算符
//+ = * / %
//+或-或*或/或%
//有计算和拼接的作用
int int1 = 5;
int int2 = 5;
uint uint1 = 9;
byte byte1 = 2;
sbyte sbyte1 = 4;
short short1 = 3;
ushort ushort1 = 2;
long long1 = 7;
ulong ulong1 = 4;
Console.WriteLine(int1+ int2);//10
//GetType().ToString()前面的是显示数据类型后面的是转为字符串类型
Console.WriteLine((byte1 + int1).GetType().ToString());//7 int32
Console.WriteLine(sbyte1+int1);//9
Console.WriteLine(short1 + long1);//10
Console.WriteLine(sbyte1 + uint1);//13
Console.WriteLine((sbyte1 + uint1).GetType().ToString());//int64
Console.WriteLine(long1 + ushort1);//9
Console.WriteLine(long1 - ushort1);//5
Console.WriteLine(ushort1 + byte1);//4
//具有二义性
//ulong与有符整数相加减乘除取余时就有二义性
//Console.WriteLine(ulong1 + short1);
//Console.WriteLine(ulong1 + int1);
//Console.WriteLine(ulong1 + long1);
//Console.WriteLine(ulong1 - long1);
//Console.WriteLine(ulong1 * long1);
//Console.WriteLine(ulong1 / long1);
//Console.WriteLine(ulong1 % long1);
//单字符类型自动转为ASCLLL码
//与ulong进行运算能进行
char char1= 'a';
Console.WriteLine(char1+int1);//102
Console.WriteLine(char1-int1);//92
Console.WriteLine((char1+int1).GetType().ToString());// 结果为int32
Console.WriteLine(char1 - ulong1);//93
Console.WriteLine(char1 % ulong1);//1
Console.WriteLine(char1 * ulong1);//388
Console.WriteLine(char1 / ulong1);//24
//运算符-,/,*,%无法用于字符串类型和整数类型的操作数
string str1 = "123";
Console.WriteLine(str1+char1);//123a
Console.WriteLine(str1+int1);//1235
//Console.WriteLine(str1-ulong1);
float float1 = 1.466f;
Console.WriteLine(int1+float1);//6.466
double double1 = 3.455567d;
Console.WriteLine((float1+double1).GetType().ToString());//4.92156696089935 Double
//运算符+,-,/,*,%无法用于decimal和float或double计算
decimal decimal1 = 3.4m;
//Console.WriteLine(float1%decimal1);
//Console.WriteLine(double1+decimal1);
Console.WriteLine(decimal1 + int1);//8.4
//++ --
int int123 = 200;
Console.WriteLine(int123++);//200
Console.WriteLine(int123);//201
Console.WriteLine(int123--);//201
Console.WriteLine(int123);//200
Console.WriteLine(++int123);//201
Console.WriteLine(int123);//201
Console.WriteLine(--int123);//200
Console.WriteLine(int123);//200
Console.WriteLine((++int123)*(int123--));//40401
int int1234 = 10;
Console.WriteLine((int1234--)*(--int1234));//80
Console.WriteLine((int1234--) * (int1234++) % (++int1234));//2
Console.WriteLine((int1234++)-(++int1234)-(int1234--)+(++int1234));//-2
Console.WriteLine((--int1234)+(int1234++)-(int1234--)-(int1234++));//-1
关系运算符
//关系运算符
//>,<,>=,<=,==,!=
//char 与 string无法比较
int int234 = 10;
int int235 = 20;
int int236 = 30;
long long234 = 100;
float float234 = 10.0f;
double double234 = 20.0d;
decimal decimal234 = 30.0m;
string string234 = "a";
string string235 = "123";
string string236 = "123";
char char234 = 'a';
bool bool123 = int234 > long234;
bool bool34 = int236 != long234;
Console.WriteLine(bool123);
bool bool124 = int235 < char234;
bool bool120 = char234 < float234;
bool bool127 = char234 < double234;
bool bool128 = char234 > decimal234;
Console.WriteLine(bool124);
//bool bool125 = char234 == string234;
//bool bool34 = string234 == float234;
bool bool125 = string234 == string235;
bool bool126 = string235 == string236;
//Equals()字符串对象提供的内置方法判断两个字符串是否相等
bool bool23 =string234.Equals(string235);//false
bool bool24 = string235.Equals(string236);//true
Console.WriteLine(bool23);
Console.WriteLine(bool24);
逻辑运算符
这个要注意符号的优先级
!&& ||从左往右
& | ^ ~ 10进制用到
//逻辑运算符
//&&与 ||或 !非
//与数学的且或非相似
int intNumber = 100;
int intNumber2 = 200;
int intNumber3 = 300;
char charNumber = 'a';
//&&全true才true,有一个false才false
// true false
bool boolean13 = intNumber < intNumber2&&intNumber>intNumber3;
Console.WriteLine(boolean13);
//||有一个true都为true
// false true
bool bool14 = intNumber > intNumber2||intNumber>charNumber;
Console.WriteLine(bool14);
//!取反
//int a=4; !a=4*3*2*1 a的乘阶
Console.WriteLine(!bool14);
//优先级
// ! && || 从左往右 !最先
// true false true
bool bool15 = intNumber < intNumber2&&intNumber>intNumber3||intNumber>charNumber;
Console.WriteLine(bool15);
赋值运算符
int a=10*=2;这样写是错误的
int a=10*2;正确
//赋值运算符
//=、+=、-=、*=、/=、%=
int intNumber4 = 1;
intNumber4 += 50;
intNumber4 -= 4;
intNumber4 *= 10;
intNumber4 /= 10;
intNumber4 %= 10;
Console.WriteLine(intNumber4);//7
三目(三元)运算符
格式:判断条件 ? "正确输出" : "错误输出"
判断条件:跟bool类关联就是true或false
正确输出:true输出这一项内的字符
错误输出:false输出这一项内的字符
//三目(三元)运算符 格式:判断条件 ? "正确输出" : "错误输出"
string str = intNumber4 < char234 ? "正确" : "错误";
Console.WriteLine(str);
Console.WriteLine(intNumber4>char234 ? "true":"false");
字符串转数字
TryParse()
注意有out是intNumber是可以无赋值
boolNumber中strNumber转化为int类型并赋值给 out intNumber返回给intNumber,在这里intNumber被赋值了而非引用
//字符串类型转整数类型
string strNumber = "123";
int intNumber;
bool boolNumber = int.TryParse(strNumber,out intNumber);
Console.WriteLine(intNumber);
Console.WriteLine(boolNumber ? "正确输出" : "错误输出");
sizeof()显示数据类型的大小
Console.WriteLine(sizeof(int));
//4
GetType()查看当前数据类型
string strNumber = "234";
int intNumber = int.Parse(strNumber);
Console.WriteLine(intNumber.GetType().ToString());
//System.Int32
if语句
int intNumber = 0;
//单等号只能赋值
//这里要注意是双等号==
if (intNumber == 0)
{
Console.WriteLine("hai");
}
格式:if(条件表达式){代码}
//if语句
//格式:if(条件表达式){}
//if的条件表达式为true是才会执行该if语句的{}中的代码,否则会跳过
//if语句与if语句是分开的,第一个执行完就会执行下一个
bool boolNumber = true;
if (boolNumber)
{
Console.WriteLine("1234");
}
if (boolNumber)
{
Console.WriteLine("你好");
}
if--else
if满足条件并执行后else就不在执行
//if--else语句
//if条件为false时,才会执行else
int intNumber = 0;
if (0 == intNumber)
{
}
else
{
}
if--else if--else
if或else if 满足条件后就不在执行要都不满足则执行else
else{}是可以去掉的
//if--else if语句
//else if 可以有很多个
if (!boolNumber)
{
}
else if (false)
{
}
else if (false)
{
}
else { }
switch语句
switch语句能做到的if语句都能做到反之则不然
//switch语句
//多个case是可以连接如case 1:case 2:运行case 2:中的代码
//break只是跳出switch语句 ,然后执行之后的代码
//default可加可不加
int intA = 3;
switch (intA)
{
case 1:
case 2:
Console.WriteLine("case 2");
break;
case 3:
Console.WriteLine("switch");
break;
default:
break;
}
goto语句
下列Login只是一个标签可以改
Name:
代码
goto Name;到这结束并从新从Name:后开始运行本质就是循环
//goto 语句 指定语句跳转
//Login可以改成任意名跟变量名一样
//aaa:
//goto aaa;
//Login是会重复输出的会报错
//也就是死循环
//相当与将整个Login内的代码重复运行
Login:
Console.WriteLine("请输入账号");
string str = Console.ReadLine();
bool boolStr = str.Equals("123");
if (boolStr)
{
Console.WriteLine("正确");
}
else
{
goto Login;
}
while循环
//while循环
//格式:while(条件表达式){}
//在没有intNum--时while会无限循环
int intNum = 3;
while (intNum > 0)
{
Console.WriteLine("while");
intNum--;
}
//while嵌套
//(最外层的while执行一次内层while执行完),再次执行这个循环直到结束
while (intNum > 0)
{
Console.WriteLine("1");
while (intNum > 1)
{
Console.WriteLine("2");
}
intNum--;
}
do--while循环
格式:do{}while();
注意:do--while最少执行一次并且在do--while里while();后面是有英文引号
//do{}while(条件表达式);
//注意:这里的while()后是有“;”英文引号
//do--while至少执行一次
bool bool1 = true;
do
{
Console.WriteLine("do--while");
bool1 = false;
} while (bool1);
int Name;
bool boolMr;
do
{
Console.WriteLine("请输入密码");
string strValue = Console.ReadLine();
boolMr=int.TryParse(strValue, out Name);
if (boolMr&&Name==123)
{
boolMr = false;
Console.WriteLine("密码正确");
}
else
{
boolMr = true;
Console.WriteLine("密码错误");
}
} while (boolMr);
for循环
break:运行到break会跳出整个循环
continue:跳出指定的循环
都与if语句联动最好
//for循环
//格式:for(初始化变量;条件表达式;变量的自增或自减){}
intNumber = 10;
for (int i = 0; i < intNumber; i++)
{
Console.Write(i + " ");
}
Console.WriteLine();
for (int i = 0; i < 4; i++)
{
Console.WriteLine(i);
//输出一个零后跳出循环
break;
}
for (int i = 0; i < 4; i++)
{
Console.WriteLine(i);
//运行到2跳出循环
if (i==2)
{
break;
}
}
for (int i = 0; i < 4; i++)
{
Console.WriteLine(i);
//continue放在这没有任何用处
continue;
}
无限循环
//break跳出循环
//for (; ; ) { }
//while(true){}
访问修饰符
各种类,方法等的访问级别
分类
解决方案下是一个个项目
每个项目都是一个程序集
只有public可以访问其他程序集
public:最高级别的访问修饰符,能够在任何地方访问该成员
以下是只能访问程序集内
internal:成员能够在程序集内的任何地方被访问
private:成员只能在所属类中被访问
protected:成员在它的所属类或派生类中被访问
protected internal:同一程序集中的同一类或派生类都可以访问该类型
private protected:同一程序集该类型或成员可以从class派生的类型访问
使用public访问修饰符的类在不同程序集时需要在 解决方案下的本来项目要引用别的项目中的类时要在引用中添加别的项目并在本来的项目添加新引入的命名空间 useing 引用的项目名;
结构体
格式:struct 结构体名{}
结构体是值类型
结构体无法被子类继承,且只能继承接口并实现
结构体中的方法传入的参数默认是值类型,而类则是引用类型
结构体不能使用析构函数
结构体不能定义无参构造函数
结构体能用new创建对象,也能不使用new。格式: 结构名 对象名;
结构体可以在类内也可以在类外
当结构体在类外 或 类内 要分栈和堆
在类外时是存储在栈内
再类内时是存储在堆内
internal class Program
{
static void Main(string[] args)
{
//结构体可以不使用new
Vertor3 vert1;
vert1.x=1;
Vertor3 vertor3 = new Vertor3();
vertor3.Vertor1();
Vertor3 vertor1 = new Vertor3(3,4,5);
Vertor3 v1;
v1.x = 10;
v1.x = 20;
//需要实例才能使用方法
//v1.Vertor1();
Console.ReadKey();
}
}
//结构体是值类型
//位于类外时是存储在栈内,也可以位于类内则是位于堆内
//结构体是无法继承的只能在这个类中调用
//结构体只有构造函数没有析构函数
//结构体可以没有显式的构造函数
public struct Vertor3
{
public double x;
private double y;
private double z;
public void Vertor1()
{
Console.WriteLine("avc");
}
public Vertor3(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
调用结构体中的方法时需要赋值也就是实例化
枚举
关键字:enum
枚举是值类型,用enum声明。
作用:枚举是描述一组整数值的结构,使数字更有意义。
枚举可以有访问修饰符,只能是public或internal,但枚举的成员默认public并不允许写public。
枚举可以放在类内,也可以放在类外
枚举都是隐式密封的,不能有派生类(子类)
枚举是一组整型常量,索引默认从0开始,也可以自己定义,但你定义的那个数据之后的数据默认加1。
internal class Program
{
static void Main(string[] args)
{
//值类型的结构体和枚举都可以不使用new
EnumClass enumClass = new EnumClass();
enumClass = EnumClass.Monday;
Console.WriteLine(enumClass);
int a= (int)enumClass;
Console.WriteLine(a);//0
EnumClass enumClass1 = EnumClass.Monday;
Console.ReadKey();
}
enum EnumProgram
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
}
enum EnumClass
{
Monday,
Tuesday,
Wednesday,
Thursday=10,
Friday,//11
Saturday,//12
Sunday//13
}
方法(函数)
方法是包含一系列语句的代码块,方法必须在类或结构体中
类就是格式:class 类名{}
方法
方法是引用类型
非静态的 声明: 访问修饰符 返回值 方法名(形式参数){}
访问:实例化类名 比如有一个Class1的类
Class1 class = new Class1();
class.方法名(实参);
动态的 声明 : 访问修饰符 static 返回值 函数名(形式参数){}
访问:在这个类中直接通过 函数名(实参);调用
在不同的类时则是 类名.函数名(实参);
返回值:有返回值时 返回值是返回的数据的数据类型,并在大括号内用格式: return 返回的数据;
用了return后会直接跳出方法后面的代码不在运行
无返回值:直接为 void
形式参数简称形参 在调用时的小括号内的叫实参
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Day3_25_Mothod
{
internal class Program
{
//入口方法
//静态方法
static void Main(string[] args)
{
//方法
//静态方法 非静态方法
//在静态方法中调用静态方法 类名.方法名();
//在同一类中时,不用加类名加点
TestMothod();
//不在同一类时,一定要使用类名打点
Class1.TestMothed();
//不在同一命名空间时,要使用命名空间名打点类名打点
Day3_25_Mothod.Class1.TestMothed();
//方法
//作用
//方法是一系列语句的代码块,方法必须在类中声明
//优点:减少了代码的重复性 方法体现了C#语言的封装性
//非静态方法需要实例化该方法所处的类
// 对象名
Program program = new Program();
//对象名.方法名();
program.TestMothod1();
//分类
//访问修饰符 无参数 无返回值 静态和非静态
int a = program.TestMothod2();
Console.WriteLine(a);
program.TestMothod3(3,4,5,6,7);
int b = program.TestMothod4(3, 6);
Console.WriteLine(b);
Console.ReadKey();
}
internal int TestMothod2()
{
int a = 5;
return a;
}
internal void TestMothod3(int a,params int[] b)
{
b[2] = a;
for (int i = 0;i<b.Length; i++)
{
Console.WriteLine(b[i]);
}
}
internal int TestMothod4(int a, int b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
}
static void TestMothod() { }
public void TestMothod1() { }
}
class Class1
{
internal static void TestMothed() { }
}
}
namespace Day3_25_Mothod
{
class Class2
{
internal static void TestMothed() { }
}
}
输出形参ref,out
关键字:ref 和out
注意:ref定义了在方法中可以不用
out定义了在方法中必须使用,且使用方法和return是一样的必须设定返回值
out可以定义不止一个
internal class Program
{
static void Main(string[] args)
{
//ref和out
//引用参数是对一个变量内存位置的引用不会创建新的存储位置
int a = 10;
int b = 20;
Program program = new Program();
program.Mothod(a,b);
Console.WriteLine($"a的值:{a},b的值{b}");
//ref会返回已被更改的形参从而影响传入的变量
program.Mothod1(ref a,ref b);
Console.WriteLine($"a的值:{a},b的值{b}");
//输出参数
//out
//与ref不同out参数写了必须要在方法或函数中使用
//声明一个变量用于接收out int result
int result;
program.Mothod2(a,b,out result);
Console.WriteLine($"result的值:{result}");
string strNumber = "1345";
int intNumber;
//TryParse()类型转换
int.TryParse(strNumber,out intNumber);
Console.WriteLine(intNumber);
Console.WriteLine("a+b的值:"+Mothod_1(a,b));
string str;
Mothod_2(a, b,out str);
Console.WriteLine(str);
Console.ReadKey();
}
internal void Mothod(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
//ref写了可以不用跟Mothod方法中的参数一样
internal void Mothod1(ref int a,ref int b)
{
int temp = a;
a = b;
b = temp;
}
internal void Mothod2( int a, int b,out int result)
{
int temp = a;
a = b;
b = temp;
result = a + b;
}
static int Mothod_1(int a, int b)
{
return a + b;
//返回值用于if语句时要注意必须有返回值
//if (a>=b) { return a; }else if (a < b) { return a; }else { return -1; }
}
static void Mothod_2(int a,int b,out string strNumber)
{
//out用于if语句时要注意必须要有返回值
if (Mothod_1(a, b) > 10)
{
strNumber = "和大于10";
}
else
{
strNumber = "和小于等于10";
}
}
}
可变参数params
params放在形参的最后面,并只有一个
params的参数只能是一维数组
static void Main(string[] args)
{
Mothod("abc",2,3,4,6,7,8);
}
static void Mothod(string strNum , params int[] a)
{
foreach(int b in a)
{
Console.WriteLine(b);
}
}
递归
在方法中调用方法
static void Main(string[] ages)
{
//1-100的和
int intNumber = 100;
Console.WriteLine($"递归Method:{Method(intNumber)});//5050
Console.WriteLine($"递归Method1:{Method1(intNumber)});//5050
Console.ReadKey();
}
static int Method(int num)
{
if(num==1)
{
return 1;
}
return num + Method(num-1);
}
static int Method1(int num)
{
if(num==1)
{
return 1;
}
num--;
//这里的加1是因为该函数每运行一次会少1(最后一次除外),就是少运行了一次num为4时
return num+1+Method1(num);
}
栈和堆
值类型存储在栈内
引用类型存储在堆内
值类型:整数类型、浮点型、字符型、布尔类型、struct(结构)、enum(枚举)
引用类型:字符串、类、接口、数组、集合、委托
栈的容量小,运行速度快
堆的容量大,运行速度慢
数组
数组在使用时必须定义元素的数量或设定有元素否则为空,无论在哪都无法使用
在方法中使用时与List<T>泛型不同不需要返回值
不可变数组是存储相同类型元素固定数组大小的集合
多维数组(一维数组,交错数组除外)内的一维数组长度要相同,长度:元素的数量
分为:
一维数组
int[] intArray = new int[] {};
intArray[索引];
//索引是从0开始
//下面的5是数组中的元素数量,未赋值时每个元素都为0。如果加大括号{}那么必须写元素,如:二
一、 int[] intArray = new int[5];
二、 int[] intArray = new int[4]{1,2,3,4}
internal class Program
{
//Program
int a;
//struct
struct Mothod
{
public int a;
}
static void Main(string[] args)
{
数组
byte
//byte[] byteArray = { };
//byte[] byteArray1 = new byte[5];
//byte[] byteArray2 = new byte[5] { 1, 2, 3, 44, 5 };
//byte[] byteArray3 = new byte[] { };
sbyte
//sbyte[] sbyteArray = { };
//sbyte[] sbyteArray1 = new sbyte[5];
//sbyte[] sbyteArray2 = new sbyte[5] { 1, 2, 3, 4, 5 }; ;
//sbyte[] sbyteArray3 = new sbyte[] { };
int
//int[] intArray = { };
//int[] intArray1 = new int[5];
//int[] intArray2 = new int[5] { 1, 2, 3, 4, 5 };
//int[] intArray3 = new int[] { };
uint
//uint[] uintArray = { };
//uint[] uintArray1 = new uint[5];
//uint[] uintArray2 = new uint[5] { 1, 2, 3, 4, 5 };
//uint[] uintArray3 = new uint[] { };
short
//short[] shortArray = { };
//short[] shortArray1 = new short[5];
//short[] shortArray2 = new short[5] { 1, 2, 3, 4, 4 };
//short[] shortArray3 = new short[] { };
ushort
//ushort[] ushortArray = { };
//ushort[] ushortArray1 = new ushort[4];
//ushort[] ushortArray2 = new ushort[4] { 1, 2, 3, 4, };
//ushort[] ushortArray3 = new ushort[] { };
long
//long[] longArray = { };
//long[] longArray1 = new long[5];
//long[] longArray2 = new long[5] { 1, 2, 3, 4, 4 };
//long[] longArray3 = new long[] { };
ulong
//ulong[] ulongArray = { };
//ulong[] ulongArray1 = new ulong[5];
//ulong[] ulongArray2 = new ulong[5] { 1, 2, 3, 6, 7 };
//ulong[] ulongArray3 = new ulong[] { };
object
//object[] objectArray = { };
//object[] objectArray1 = new object[5];
//object[] objectArray2 = new object[5] { 1, 2, 3, 66, 77 };
//object[] objectArray3 = new object[] { };
char
//char[] charArray = { };
//char[] charArray1 = new char[5];
//char[] charArray2 = new char[5] { 'a', 'c', 'e', 'f', 'd' };
//char[] charArray3 = new char[] { };
string
//string[] stringArray = { };
//string[] stringArrry1 = new string[4];
//string[] stringArray2 = new string[4] { "2", "3", "4", "a" };
//string[] stringArray3 = new string[] { };
float
//float[] floatArray = { };
//float[] floatArray1 = new float[4];
//float[] floatArray2 = new float[3] { 2.3f, 4.5f, 6.4f };
//float[] floatArray3 = new float[] { };
double
//double[] doubleArray = { };
//double[] doubleArray1 = new double[3];
//double[] doubleArray2 = new double[3] { 2.3d, 3.4d, 6.4d };
//double[] doubleArray3 = new double[] { };
decimal
//decimal[] decimalArray = { };
//decimal[] decimalArray1 = new decimal[4];
//decimal[] decimalArray2 = new decimal[3] { 2.4m, 4.6m, 7.5m };
//decimal[] decimalArray3 = new decimal[] { };
dynamic
//dynamic[] dynamicArray = { };
//dynamic[] dynamicArray1 = new dynamic[4];
//dynamic[] dynamicArray2 = new dynamic[3] { 1, 23, 3 };
//dynamic[] dynamicArray3 = new dynamic[] { };
类
//Program[] programs;
//Program[] program = new Program[3];
//program[0] = new Program();
//List<Program> program= new List<Program>();
struct
//Mothod[] mothods = new Mothod[3];
遍历foreach
//int[] intNum = { 0, 1, 2, 3 };
//foreach (int i in intNum)
//{
// Console.Write(i + " ");
//}
//Console.WriteLine();
//for (int i = 0; i < intNum.Length; i++)
//{
// Console.WriteLine(intNum[i]);
//}
MothodPoint(MothodPerson());
Console.ReadKey();
}
static int MothodPerson()
{
aa:
Console.WriteLine("请输入学生总数");
int person;
bool a = int.TryParse(Console.ReadLine(), out person);
if (!a)
{
Console.WriteLine("学生总数输入错误,请重新输入");
goto aa;
}
return person;
}
static void MothodPoint(int person)
{
double[] doublePoint = new double[person];
double point;
bool poi;
for (int i = 0; i < person; i++)
{
bb:
Console.WriteLine("请输入学生分数:(0-100)");
poi = double.TryParse(Console.ReadLine(), out point);
if (!poi)
{
Console.WriteLine("分数输入有问题,请重新输入");
goto bb;
}
int a = (int)(point *= 10);
point = a;
point /= 10;
doublePoint[i] = point;
}
//从大到小排序
//dig(doublePoint);
Console.WriteLine("输出所有学生分数");
int b = 1;
foreach (int i in doublePoint)
{
Console.Write($"学生:{b} ");
Console.WriteLine($"成绩:{i}");
b++;
}
}
//从大到小排序
static void dig(double[] doublePoint)
{
for (int j = 0; j < doublePoint.Length - 1; j++)
{
for (int i = 0; i < doublePoint.Length - j - 1; i++)
{
if (doublePoint[i] < doublePoint[i + 1])
{
double result = doublePoint[i];
doublePoint[i] = doublePoint[i + 1];
doublePoint[i + 1] = result;
}
}
}
}
}
二维数组
多维数组(一维数组,交错数组除外)内的一维数组长度要相同,长度:元素的数量
GetLength()在多维数组中使用,用来判断每个大括号{}内元素的长度
{{},{}}外面{}为数组内部{}当为元素
数组名.GetLength(0);指的是外部{}为数组时该数组所包含的元素长度
数组名.GetLength(1);指的是内部{}为数组时该数组所包含的元素长度
//二维数组
int[,] ints2 = new int[,] { { 1, 2, 3, 4 }, { 2, 3, 4, 5 } };
for (int i = 0; i < ints2.GetLength(0); i++)
{
for (int j = 0; j < ints2.GetLength(1); j++)
{
Console.Write(ints2[i,j]+" ");
}
}
Console.WriteLine();
decimal[,] decimal1 = new decimal[,] { };
char[,] char1 = new char[2,2] { { 'a', 'b' }, { 'c', 'd' } };
for(int i = 0;i < char1.GetLength(0); i++)
{
for(int j = 0;j < char1.GetLength(1); j++)
{
Console.Write(char1[i,j]+" ");
}
}
Console.WriteLine();
string[,] string1 = new string[2, 4] { { "asd", "dfd", "daa", "abc" }, { "sddf", "354", "rt66", "rrw" } };
for (int i = 0; i < string1.GetLength(0); i++)
{
for (int j = 0; j < string1.GetLength(1); j++)
{
Console.Write(string1[i,j]+" ");
}
}
Console.WriteLine();
Console.ReadKey();
三位数组
多维数组(一维数组除外)内的一维数组长度要相同,长度:元素的数量
//三维数组
int[,,] ints3 = new int[3, 4, 2] { { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }, { { 9, 10 }, { 11, 12 }, { 13, 14 }, { 15, 16 } }, { { 17, 18 }, { 19, 20 }, { 21, 22 }, { 23, 24 } } };
for(int i = 0;i < ints3.GetLength(0); i++)
{
for(int j = 0;j < ints3.GetLength(1); j++)
{
for (int s = 0; s < ints3.GetLength(2); s++)
{
Console.Write(ints3[i, j, s] + " ");
}
}
}
Console.WriteLine();
Console.ReadKey();
交错数组
//交错数组
int[][] ints1 = new int[3][] { new int[3] { 1, 2, 3 }, new int[4] { 4, 5, 6,7 }, new int[5] { 7, 8, 9 ,10,11} };
for (int i = 0; i < ints1.Length; i++)
{
for (int j = 0; j < ints1[i].Length; j++)
{
Console.Write(ints1[i][j]+" ");
}
}
Console.WriteLine();
foreach (int[] a in ints1)
{
foreach (int b in a)
{
Console.Write(b+" ");
}
}
Console.ReadKey();
Array类
Array intArray = Array.CreateInstance(typeof(int),5);
int[] intArray1 = new int[5];//跟上面那个一样,只不过访问方式不同
intArray.SetValue(3,0);将值为3赋给第一个元素,其实就是intArray1[0]=3;
intArray.GetValue(0);获取intArray的位于0的值,就是intArray1[0];
Array.IndexOf(intArray,3);查找3在intArray中的第几位(索引),若不存在3则返回-1;
Array.Sort(intArray1);将数组从小到大排序,仅限一维数组;
Array.Reverse(intArray1);逆置数组
Array.Clear(intArray1,2,2);将数组从第3位索引开始初始化2位元素,不要超过索引;
//Array类
//创建一个一维数组
//下面这个数组值都是0
// Array类 创建从0开始的索引(指向数据类型(数据类型),长度)
Array intArray1 = Array.CreateInstance(typeof(int),4);
//设置元素SetValue(值,索引); 索引从0开始 值 是赋给 索引
intArray1.SetValue(3, 0);
//读取元素GetValue(索引);
Console.WriteLine(intArray1.GetValue(0));//3
foreach(int i in intArray1)
{
Console.Write(i+" ");//3 0 0 0
}
Console.WriteLine();
//二维数组
int[,] intArra = new int[2, 3] { { 1, 3, 4 },{ 3, 5, 6 } };
for (int i = 0; i < intArra.GetLength(0); i++)
{
for (int j = 0; j < intArra.GetLength(1); j++)
{
Console.Write(intArra[i,j]+" ");//1 3 4 3 5 6
}
}
Console.WriteLine();
Array intArray2 = Array.CreateInstance(typeof(int),4,2);
intArray2.SetValue(3, 0,1);
intArray2.SetValue(2, 1,1);
foreach(int i in intArray2)
{
Console.Write(i+" ");//0 3 0 2 0 0
}
Console.WriteLine();
int[] intArray3 = new int[5] { 1, 4, 62, 3, 2 };
Array intArray4 = Array.CreateInstance(typeof (int),4);
//深复制 4不能超出这两个数组的索引
Array.Copy(intArray3, intArray4, 4);
foreach(int i in intArray4)
{
Console.Write(i+" ");//1 4 62 3
}
Console.WriteLine();
int[] intarraf = new int[] { 1, 2, 2, 4, 4, 4, 4, 4, 3 };
//逗号前的是要查找的数组,逗号后的是查找(遍历)的元素
//查找到的元素会显示这个元素在数组中对应的从0开始的索引,找不到则显示为-1
//IndexOf() 1 -1
Console.WriteLine(Array.IndexOf(intArray1,0));//1
Console.WriteLine(Array.IndexOf(intarraf,2));//1
int intarr1 = 4;
for (int i = 0; i < intarraf.Length; i++)
{
if (intarraf[i]==intarr1)
{
Console.WriteLine(i);//3
break;
}
else if (intarraf[i] != intarr1&&intarraf.Length-1==i)
{
Console.WriteLine(intarraf[i] != intarr1 ? "-1" : "存在");
}
}
//仅能对一维数组使用
//Array.Sort()从小到大排序
Array.Sort(intArray3);
foreach(int i in intArray3)
{
Console.Write(i+" ");//1 2 3 4 62
}
Console.WriteLine();
int[] intSort = new int[] { 56, 34, 23, 78, 4, 2, 8 ,1 };
for (int i = 0; i < intSort.Length; i++)
{
for (int j = 0; j < intSort.Length-1; j++)
{
if (intSort[i] < intSort[j])
{
int a = intSort[i];
intSort[i] = intSort[j];
intSort[j] = a;
}
}
}
foreach (int item in intSort)
{
Console.Write(item+" ");
}
Console.WriteLine();
//Array.Reverse()数组逆置
Array.Reverse(intArray3);
foreach (int i in intArray3)
{
Console.Write(i+" ");
}
Console.WriteLine();
int[] intReverse = new int[] { 56, 34, 23, 78, 4, 2, 8, 1 };
int max =intReverse.Length-1;
for (int i = 0; i < intReverse.Length/2; i++)
{
int reverse = intReverse[i];
intReverse[i] = intReverse[max];
intReverse[max] = reverse;
max--;
}
foreach (int i in intReverse)
{
Console.Write(i+" ");//1 8 2 3 78 23 34 56
}
Console.WriteLine();
//Array.Clear()将数组某个范围的元素初始化
// 第一个2是起始位,第二个2是初始化的元素数量
Array.Clear(intArray3, 2, 2);
foreach(int i in intArray3)
{
Console.Write(i+" ");
}
Console.WriteLine();
int[] intClear = new int[] { 56, 34, 23, 78, 4, 2, 8, 1 };
//从第几位元素开始
int first = 2;
//初始化的元素个数
int second = 2;
for (int i = first-1;i < first+second-1; i++)
{
intClear[i] = 0;
}
foreach(int i in intClear)
{
Console.Write(i+" ");
}
Console.WriteLine();
Console.ReadKey();
不可变字符串
在不赋新值的情况下,以下代码都是在克隆体(深复制)上运行并不影响原值
int[] inta = new int[] {1,2,3,4,5};
//从数组转为字符串
string strNum = string.Concat(inta);
string类型是引用类型
以下也可以用在数组上
Array类是无法用在string strNumber = "afdff";这种。
数组是可以使用Array类 string[] strNumber1 = {};
//不可变字符串
//不可变字符串原来的值是不会发生改变的(用以下词)
//不可变字符串改变的是克隆的
//Copy是深复制不会影响原值
string strNumber = "avdcvc";
string strNumber1 = "fdthh";
//比较两个字符串,相同输出true,反之输出false
//变量名.Equals(变量名1);
Console.WriteLine(strNumber.Equals(strNumber1));
//分割字符串
//变量名.Split('作为分割的字符或符号'); 变量名.Split('')[索引];
//单引号内为空是无发分割,括号内为空则会将一整个字符串当成一个元素
Console.WriteLine(strNumber.Split('v')[0]);//a
//截取字符从索引开始到最后,返回一个新字符串,原字符串不变
//变量名.Substring(索引); 变量名.Substring(索引,截取几位);
Console.WriteLine(strNumber.Substring(2));
Console.WriteLine(strNumber.Substring(2,2));
//将小写字母转为大写,返回一个新字符串,原字符串不变
//变量名.ToUpper();
Console.WriteLine(strNumber.ToUpper());
//将大写字母全部转为小写,返回一个新字符串,原字符串不变
//变量名.ToLower();
Console.WriteLine(strNumber.ToLower());
//查找字符第一次出现所在索引位置并输出该索引,找不到则输出-1
//变量名.IndexOf("要查找的字符");
Console.WriteLine(strNumber.IndexOf("a"));//0
//查找字符最后一次出现所在索引位置并输出该索引,找不到则输出-1
//变量名.LastIndexOf("要查找的字符");
Console.WriteLine(strNumber.LastIndexOf("c"));//5
//查找字符串是否是该字符开头,是输出true,不是则false
//变量名.StartsWith("开头的字符");
Console.WriteLine(strNumber.StartsWith("a"));
//查找字符串是否是该字符结尾,是输出true,不是则false
//变量名.StartsWith("结尾的字符");
Console.WriteLine(strNumber.EndsWith("a"));
//判断是否包含某个字符,是输出true,不是则false
//变量名.Contains("字符");
Console.WriteLine(strNumber.Contains("v"));
//将某个字符串中的一些字符串替换为新的字符串,返回一个新字符串,原字符串不变
//变量名.Replace("旧字符","新字符"); 变量名.Replace(变量名,变量名1); 变量名2.Replace(变量名,变量名1);
Console.WriteLine(strNumber.Replace(strNumber,strNumber1));
//判断是否为null或空 ,是则输出true,反之false
//数据类型.IsNullOrEmpty(变量名);
Console.WriteLine(string.IsNullOrEmpty(strNumber1));
string strNumber2 = " a faf gg ";
//清除字符串最前最后的空格,返回一个新字符串,原字符串不变
//变量名.Trim();
Console.WriteLine(strNumber2.Trim());
//清除字符串最前的空格,返回一个新字符串,原字符串不变
//变量名.TrimStart();
Console.WriteLine(strNumber2.TrimStart());
//清除字符串最后的空格,返回一个新字符串,原字符串不变
//变量名.TrimEnd();
Console.WriteLine(strNumber2.TrimEnd());
//在左侧添加空格达到指定长度,返回一个新字符串,原字符串不变
//PadLeft(指定的长度)
Console.WriteLine(strNumber2.PadLeft(15));
//在右侧添加空格达到指定长度,返回一个新字符串,原字符串不变
//PadRight(指定的长度)
Console.WriteLine(strNumber2.PadRight(15));
//删除指定位置的字符,返回一个新字符串,原字符串不变
//变量名.Remove(索引,删几位);
Console.WriteLine(strNumber.Remove(3,2));
//将一个字符串插入指定的字符串位置,返回一个新字符串,原字符串不变
Console.WriteLine(strNumber.Insert(3,"dff"));
//Concat连接两个集合或多个集合的元素,并组成新的集合
int[] inta = { 1, 3, 4, 5, 6, 7 };
int[] ints = { 1, 2, 3, 4, 5 };
//从数组转为字符串
string.Concat(inta);
var c = inta.Concat(ints);
foreach (var item in c)
{
Console.Write(item);
}
Console.WriteLine();
var strNum = strNumber.Concat(strNumber1);
foreach (var i in strNum)
{
Console.Write(i);
}
Console.WriteLine();
//Join
//将指定的分隔符作为连接,来组合数组
int[] intb = { 1, 3, 4, 5, 6, 7 };
string strNumber3 = string.Join("", intb);//会显示分隔符
Console.WriteLine(strNumber3); ;
//将字符串转化为单字符类型
char[] charArray = strNumber.ToCharArray();
foreach (var item in charArray)
{
Console.WriteLine(item);
}
Console.ReadKey();
可变字符串
不可变字符串用的关键字在这里也能使用
用在普通拼接上跟不可变字符串一样,改变克隆,原式不变
用在StringBuilder类上则是,改变原式
StringBuilder只会创建一个内存
//可变字符串
//会创建多余内存
//str1+str2+str3结果如下会创建两个内存,加的越多创建越多
//stra=str1+str2 str4=str3+stra
//普通拼接方式
//这是一个空字符串是有内存的
string str = string.Empty;
str += "sdf";
str += "fdf";
//不可变字符串的关键字可以在这里使用,同样只改变克隆体,原字符串不变
Console.WriteLine(str.Remove(1, 1));
Console.WriteLine(str);
//高效拼接方式
//只会创建一个内存
//StringBuilder类
StringBuilder sb = new StringBuilder();
//添加
sb.Append('a');
sb.Append("afdf");
Console.WriteLine(sb);
//插入
sb.Insert(0, "cg");
//删除
sb.Remove(3, 1);
Console.WriteLine(sb);
//修改所有对应的字符
sb.Replace("f", "o");
Console.WriteLine(sb);
//清理
sb.Clear();
Console.WriteLine(sb);
Console.ReadKey();
null 空
//null
//string str="";是会分配内存的
//string str=null;不会分配内存
//值类型不能直接为null,引用类型可以直接等于null
//可空类型与不可空类型是两种不同的类型,是需要转换的
string stra = null;
//可空类型
Nullable<int> inta = null;
Nullable<int> inta1 = 13;
int? intb = null;
int? intb2 = null;
int? intb1 = 12;
//不可空类型
int c;
int c1 = 11;
//可空类型比不可空类型大
//隐式转换
intb = c1;
//显示转换
//可为空的对象必须有一个值
//c = (int)intb2;
Console.WriteLine(intb);
//??合并运算符
//??后的值是预设值用来防止inta为空
c = inta ?? 39;//39
//当inta1不为null时赋给c的值是inta1
c = inta1 ?? 34;//13
//?.null条件运算符
//判断是否为空,是则输出null,反之实际
string strNum = null;
//抛出异常
//int? strNum2 = strNum.Length;
int? strNum3 = strNum?.Length;//strNum3为空
Console.ReadKey();
面对对象
字段
格式:访问修饰符 数据类型 字段名;
字段名:下划线加小驼峰 _nameAge
全局变量可以在这个类中随意使用,局部变量只能在方法中使用字段是全局变量字段放在类内 方法外 ,局部变量是放在方法内
字段是全局变量有默认值的,值类型默认0,引用类型默认null,局部变量没有默认值
使用字段时,字段是值类型和string类型是深拷贝(会克隆), 引用类型是浅拷贝(给原值)
静态字段和动态字段
静态字段只用通过类名来调用,加const的字段默认静态
加readonly的字段不是静态,必须在前面加static才为静态
静态字段在类加在载时创建,只创建一次
实例字段随着new的创建而创建
实例字段要通过对象名调用
一个类内不允许创建相同的字段,但允许创建与字段相同的局部变量
private int a;
public void Method()
{//局部变量
int a;
//全局变量
this.a;
}
class Class1
{
int _a;
static int _b;
const int _c = 3;
readonly int _d = 4;
static readonly int _e = 5;
//放入静态方法
public static void Struck()
{
Class1 class1 = new Class1();
//非静态在静态方法中使用需要对象
class1._a = 1;
//静态方法
_b = 2;
//常量
int int1 = _c;
//readonly
int int2 = class1._d;
int2 = _e;
}
//放入非静态方法
public void Method()
{
this._a++;
_a++;
_b++;
int int1 = _c;
//readonly
int int2 = _d;
int2 = _e;
}
}
属性
属性通常与字段联动
字段通常是private,想在这个类外使用,同时又想限制对字段的使用,就需要属性
方法虽然也能做到属性但属性更安全,方便
属性通常都用大驼峰
一个属性通常有一个get{}和set{}
get{}是只读,set{}只写
在属性set{}中 字段=值 ;不能 直接获取值 这样做是无法赋值只能是默认值或定义字段时的赋值,因为未执行该属性,只需通过实例赋值运行该属性,就能使用
class Class2
{
private int _a;
private int _b=10;
private int _c;
//可读可写
public int A { get { return _a; } set { _a = value; } }
//只读
public int B { get { return _b; } }
//属性扩展--增加字段的业务判断逻辑
public int C
{
get { return _c; }
set
{
if (value < 0 && value > 10)
{
_c = 10;
}
else
{
_c = value;
}
}
}
//系统会在底层生成相应的字段
public string Name { get;set; }
// 相当与直接给字段赋值
public int Age { get; set; } = 4;
//只读,想要只读就删掉set; 想要只写就删掉get;
public int Bge { get; } = 6;
}
构造函数
在有多个构造函数时构造函数会重载
本质就是方法,作用类创建对象时默认的方法
类默认存在构造函数,构造函数名要与类名保持一致
构造函数分为:实例构造函数和静态构造函数
实例构造函数和静态构造函数可以同时存在,一个属于对象,一个属于类
构造函数定义时会覆盖掉默认构造函数,所以你也可以在定义一个空构造函数public 类名(){}
构造函数可以定义为私有的因覆盖掉默认构造函数,所以不能创造该类的实例
静态构造函数不允许有访问修饰符和参数
静态构造函数 默认系统会自带 在类创建时 用来初始化 所有的 静态成员 系统调用即可
class Class3
{
int _a;
string _b;
static int _c;
//实例构造函数属于对象
public Class3()
{
}
public Class3(string c)
{
}
private Class3(int a)
{
}
//静态构造函数在类创建时,用来初始化所有静态成员,只进行一次
//静态构造函数属于类
static Class3()
{
}
}
class Class4
{
static void Method()
{
Class3 c = new Class3();
Class3 class3 = new Class3("df");
//不可访问
//Class3 d = new Class3(1);
Class3 d = new Class3();
}
void Method2()
{
Class3 c = new Class3();
Class3 class3 = new Class3("sfdf");
//不可访问
//Class3 d = new Class3(1);
Class3 d = new Class3();
}
}
静态类
静态类因为类是静态的,所以不能定义非静态的成员,只能定义静态的成员
静态类不能被实例,因此静态类不能继承
静态类只能有静态构造函数,但静态构造函数不允许有访问修饰符和参数
析构函数
格式:~类名(){}
垃圾回收程序,最终会销毁之前调用的对象
析构函数会自动调用,也可以强制调用
析构函数只回收 堆 内的内存,而值类型在 栈 内的使用完后会自动回收
关于什么时候回收,我们可以不用管系统会自动回收,也可以在有明确结束时强制回收
class Class1
{
public void Main(string[] args)
{
Class34 class34 = new Class34();
//为null时才会执行
class34 = null ;
GC.Collect();
Console.ReadKey();
}
}
class Class34
{
~Class34()
{
Console.WriteLine("强制回收");
}
}
面对对象的三大特性:封装,继承,多态
三个特性主要目标:安全性,灵活性,扩展性
封装
封装就是将类的某些信息隐藏起来,不允许外部访问,可以通过该类提供的公共属性和方法进行操作和访问。
封装可以通过:将字段通过属性中的get和set来实现读取和操作,属性用于将实例对象封装到类中
通过访问修饰符来控制类中数据和方法的访问权限
方法:实现细节可以隐藏起来并只暴露实现所需的最小接口
继承
解决类与类之间,属性和方法的重复问题
一个类继承另一个类,其中 被继承的类(父类 或 超类 或 基类),继承的类(子类 或 派生类)
继承的格式:子类:父类
子类可以访问父类的成员,但父类确无法访问子类的成员
class Class1
{
}
// 子类 父类
class Class2 : Class1
{
}
一个父类可以被多个子类继承,子类可以间接继承父类。一个子类b继承一个父类a,一个类c继承b,算为类c继承了b类和a类
类与类之间除接口都是单继承关系,而接口确可以被多继承(一个接口继承多个接口,一个类继承多个接口)
object是所有类的基类,如果没有继承的类,是默认继承object类
在继承中默认先调用父类构造函数,在调用子类构造函数,无论有无参数, 毕竟父类有参数,子类无参会报错。
在继承中,调用构造函数系统默认调用父类的构造函数,如果父类的构造函数有参数,而子类构造函数没有参数,想调用子类的构造函数(默认构造函数),必须在父类创建一个新的无参构造函数,在继承中会先调用父类的默认构造函数在调用子类的构造函数。
在继承中,如果父类的构造函数有参数,而子类构造函数没有参数,还想使用子类 无参 构造函数 就需要在子类构造函数()后添加 : base(对应父类构造函数的参数),会先运行父类构造函数
在父类和子类中如果有同名的方法需要通过new来指向使用的是父类和子类的方法,否则默认隐藏父类的方法
多态
多态,就是一个接口,多个功能,同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
包含:重载,重写,抽象类,接口
重载
一个类中有多个相同的方法名的方法,但参数的数据类型和不同数据类型的排序不同构成 重载
,无关返回值和是否静态。
覆盖
在继承中,子类中方法有和父类中方法同名的方法时,会自动隐藏父类的方法,而子类方法前需要加new。
重写
只有虚方法能用来重写。
虚方法
在子类与父类中的方法有方法名相同,参数也相同的方法。
关键字:virtual (父类中使用) override(子类中使用)
虚方法可以被子类重写
internal class Program
{
static void Main(string[] args)
{
ChinesePeople people = new ChinesePeople();
people.Method();
people.Method(1);
people.Method(2.3);
Console.ReadKey();
}
}
internal class People
{
public virtual void Method()
{
Console.WriteLine("无参People");
}
public virtual void Method(int number)
{
Console.WriteLine("int类型参数People");
}
public virtual int Method(double number)
{
Console.WriteLine("double类型参数People");
return 0;
}
}
internal class ChinesePeople:People
{
public override void Method()
{
base.Method();
Console.WriteLine("无参ChinesePeople");
}
public override void Method(int number)
{
base.Method(number);
Console.WriteLine("int类型参数ChinesePeople");
}
public override int Method(double number)
{
base.Method(number);
Console.WriteLine("double类型参数ChinesePeople");
return 1;
}
}
抽象类
//抽象类
//关键字:abstract override
//抽象类不能实例化 ,不能创建对象
//抽象类是单继承关系
//抽象类之间可以直接继承,不用实现
//定义的抽象成员必须实现在子类中
//定义的非静态成员和抽象成员只能通过子类使用
public abstract class AbstractClass
{
//抽象类能当普通类使用,但抽象类不能实例化,不能创建对象,所以要通过继承使用
public int _a;
//抽象类不能创建抽象字段
//public abstract int _b;
//public AbstractClass() { }
//不能定义抽象构造函数
//public abstract AbstractClass();
public abstract int Abs1 { get; }
public abstract int Abs2 { get; set; }
public abstract void AbsMethod();
//不能定义静态抽象成员
//public abstract static int Abs1 { get; }
//public abstract static void SetMethod();
}
//普通类
public class People:AbstractClass
{
public override int Abs1 => throw new NotImplementedException();
public override int Abs2 { get; set; }
public override void AbsMethod() { }
}
接口
//关键字:interface声明类 接口一般以I开头
//接口默认公开,在其内的成员也默认公开,且不允许写任何的访问修饰符
//接口只允许声明成员
//接口不能声明静态成员和虚拟的,在接口中是public的成员在子类中必须实现和加public
//接口是多继承,也可以间接继承
关于接口的使用可以通过接口的对象等于继承着这个的类new实例,但因为接口的限制只能通过这个接口的对象来调用继承这个接口的类中实现接口成员的方法。
public interface Icall
{
string Name { get; }
void Call();
}
public class Cat:Icall
{
public string Name { get; set; } = "汤姆";
public void Call()
{
Console.WriteLine("猫会叫,喵喵");
}
}
public class Dog : Icall
{
public string Name { get; set; } = "杰克";
public void Call()
{
Console.WriteLine("狗是汪汪叫");
}
}
internal class Program
{
public void Main(string[] args)
{
//限制只能使用接口中有的成员
Icall call;
call = new Dog();
call.Call();
call = new Cat();
call.Call();
}
}
密封类
关键字:sealed
sealed也能用来密封方法。
密封类就是来限制继承性
密封类跟普通类一样,但不能被继承,却能继承其他类。
密封类不能继承其他类所以,不能使用protected,以及virtual 这种必须要用到派生类的。
public sealed class SealedExample
{
public void DoSomething()
{
// 类的实现细节
}
}
// 尝试从SealedExample继承将导致编译错误
public class InvalidDerivedClass : SealedExample // 编译错误:不能从密封类“SealedExample”派生
{
// ...
}
限制符号Regex类
在C#中,如果你想要限制用户输入或字符串中只能包含特定的字符(例如,只包含字母、数字或特定的符号),你可以使用正则表达式(Regex)或简单的字符串处理方法。
以下是一些示例,展示了如何在C#中限制符号的使用:
示例1:只允许字母和数字
你可以使用正则表达式来检查一个字符串是否只包含字母和数字。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string input = "Hello123";
bool isValid = Regex.IsMatch(input, @"^[a-zA-Z0-9]+$");
Console.WriteLine(isValid); // 输出: True
input = "Hello!123";
isValid = Regex.IsMatch(input, @"^[a-zA-Z0-9]+$");
Console.WriteLine(isValid); // 输出: False
}
}
示例2:允许特定的符号
如果你想要允许特定的符号(例如,-
和 _
),你可以修改正则表达式。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string input = "Hello_World-123";
bool isValid = Regex.IsMatch(input, @"^[a-zA-Z0-9_-]+$");
Console.WriteLine(isValid); // 输出: True
input = "Hello! World-123";
isValid = Regex.IsMatch(input, @"^[a-zA-Z0-9_-]+$");
Console.WriteLine(isValid); // 输出: False
}
}
示例3:从字符串中移除不想要的符号
如果你想要从现有的字符串中移除不想要的符号,你可以使用String.Replace
方法或正则表达式。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string input = "Hello! World@123#";
string cleaned = Regex.Replace(input, @"[^\w\s-]", ""); // 移除非字母数字、空格和-的字符
Console.WriteLine(cleaned); // 输出: Hello World-123
}
}
在这个例子中,[^\w\s-]
是一个正则表达式,它匹配任何不是字母、数字、下划线、空格或短横线的字符,并使用Regex.Replace
方法将它们替换为空字符串(即移除它们)。
Math类
Math
类是 System
命名空间的一部分,它提供了一组用于执行数学运算的静态方法和属性。Math
类中的方法可以帮助你执行诸如求平方根、计算三角函数值、执行对数运算、取整、求幂等数学操作。
常用的数学运算方法
- Sqrt: 计算一个数的平方根。
- Pow: 计算一个数的指定幂。
- Abs: 计算一个数的绝对值。
- Round: 将一个数四舍五入到最接近的整数或指定的小数位数。
- Ceiling: 返回大于或等于指定数字的最小整数。
- Floor: 返回小于或等于指定数字的最大整数。
三角函数方法
- Sin: 计算一个角度的正弦值(参数是弧度)。
- Cos: 计算一个角度的余弦值(参数是弧度)。
- Tan: 计算一个角度的正切值(参数是弧度)。
对数方法
- Log: 计算一个数的自然对数(以e为底)。
- Log10: 计算一个数的以10为底的对数。
其他常用方法
- Max: 返回两个数中的较大值。
- Min: 返回两个数中的较小值。