Visual Studio 2019 快捷键
编辑相关的键盘快捷键
Shift + Ctrl + Enter :在当前行下方插入空行
Ctrl + Enter:在当前行上方插入空行
Ctrl + L :删除光标所在行
Alt + Shift + 箭头键(←,↑,↓,→) : 选择代码的自定义部分
Ctrl + Shift +} :选中匹配的括号、括号内的所有文本
Ctrl + Shift + S :保存所有文件和项目
Ctrl + K,Ctrl + C :注释选定行(按住Ctrl,先按K再按C)
Ctrl + K,Ctrl + U :取消选定行的注释(按住Ctrl,先按K再按U)
Ctrl + K,Ctrl + D :正确对齐所有代码(按住Ctrl,先按K再按D)
Ctrl+C,Ctrl+V :在没有选择的情况下 向下复制光标所在的行
两下tab :快速代码段(for,foreach循环,try, 绑定事件方法)
导航相关的键盘快捷键
Ctrl + - : 定位到之前光标所在的位置
Ctrl +Shift+ - :定位到之后光标所在的位置
调试相关的键盘快捷键
F10 : 调试单步执行
F5 : 开始调试
Shift + F5 : 停止调试
Ctrl + F5 :编译运行
F9 : 设置或删除断点
搜索相关的键盘快捷键
Ctrl + K ,Ctrl + K : 将当前行添加书签(按住Ctrl,按两次K)
Ctrl + K ,Ctrl + N : 导航至下一个书签(按住Ctrl,先按K再按N)
C#的基本数据类型:
类型 说明 大小(位) 范围 示例
byte 字节 8 0~255 byte b1;
b1 = 66;
int 整数 32 -2^31~2^31-1 (10位) int count;
count = 42;
long 整数(更大范围) 64 -2^63~2^63-1 (19位) long wait;
wait = 42L;
float 浮点数 32 -3.4*10^-38~3.4*10^38 float away;
away = 0.42F;
double 双精度(浮点数) 64 ±5.0*10^-324~±1.7*10^308 double trouble
trouble = 0.42;
decimal 货币值 128 28位小数 decimal coin;
coin = 0.42M;
string 字符序列 每个字符16位 不适用 string vest;
vest=“fortytwo”;
char 单字符 16 单字符 char grill; grill = 'x';
bool 布尔值 8 true或false bool teeth; teeth = false;
C#中的转义字符:
1、转义字符有特定含义。
2、Unicode是一个16进制的数字,表示这个字符在内存中以哪个数字存储,也可以使用Unicode来代表一个转义字符
(u加上十六进制值):
"I's siki!" "Iu0027s siki!"
3、如果我们不想去识别字符串的转义字符,可以在字符串前面加上一个@符号(除了双引号其他转义字符都不在识别)。
例如:
"c:xxxxxxxx.doc" => "c:xxxxxxxx.doc"
转义序列 产生的字符 字符Unicode值
' 单引号 0x0027
'' 双引号 0x0022
反斜杠 0x005c
0 空 0x0000
a 警告(产生蜂鸣) 0x0007
b 退格 0x0008
f 换页 0x000c
n 换行 0x000a
r 回车 0x000d
t 水平制表符 0x0009
v 垂直制表符 0x000b
C#语法基础:
一、命名规范:
遵守命名规范可以让程序结构更加清晰,更易于阅读。
Camel命名法(驼峰命名法):首字母小写,以后每个单词的首字母大写——用于变量
Pascal命名法:每个单词的第一个字母都大写,如果使用到英文单词的缩写,全部使用大写(PI HP MP)——用于方法和类
二、break/continue:
return:是用来终止方法的,不是用来终止循环的.
continue:用于结束当前循环.
break:用于结束循环语句.
三、类型转换:
隐式转换:
int myInt = 123;
float myfloat = myInt;
显示转换:
float myfloat =12.2f;
myInt = (int)myfloat; # 显示转换
Convert.ToInt32(val); # 显示转换为32位int
Convert.ToString(val); # 显示转换为String
四、for语句的执行过程:
五、委托:
委托(delegate)是一种存储函数引用的类型。
委托的定义指定了一个返回类型和一个参数列表
定义委托之后,就可以声明该委托类型的变量,接着就可以把一个函数赋值给这个变量。
六、匿名类型: 使用var声明的匿名类型,当赋初始值的时候,这个变量的类型就被确定下来,并且以后不可以修改:
var var1 = 32;
以后var1就是int形了
七、基础语法演示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
//枚举
enum state
{
Pause,
Failed,
Success,
Start
}
//结构体
struct Position
{
public float x;
public float y;
public float z;
}
//定义和使用函数
static int add(int a, int b)
{
return a + b;
}
//参数数组
static int Plus(params int[] array)
{
int sum = 0;
for (int i = 0; i < array.Length; i++)
{
sum += array[i];
}
return sum;
}
//函数
static int sum(int[] array)
{
int add = 0;
for (int i = 0; i < array.Length; i++)
{
add += array[i];
}
return add;
}
//结构体函数
struct CustomerName
{
public string firstName;
public string lastName;
public string GetName()
{
return firstName + " " + lastName;
}
}
//委托的定义
public delegate double MyDelegate(double param1, double param2);
//定义函数供给委托使用
static double Multiply(double param1, double param2)
{
return param1 * param2;
}
static double Divide(double param1,double param2)
{
return param1 / param2;
}
static void Main()
{
//if判断:
//bool var1 = 50 > 30;
//if (var1) Console.WriteLine("为真"+var1);
//else Console.WriteLine("为假"+var1);
//三元运算
//int myinteger = 100;
//string resStr = (myinteger < 10) ? "less than 10" : "Greaer than or equal to 10";
//Console.WriteLine(resStr);
//swith case语句
//char alpha = Convert.ToChar(Console.ReadLine());
//switch (alpha)
//{
// case 'a':Console.WriteLine("我是A"); break;
// case 'b':Console.WriteLine("我是B"); break;
// case 'c':Console.WriteLine("我是C"); break;
//}
//do while语句
//int num = 0;
//do
//{
// num++;
// Console.WriteLine(num);
//} while (num<=9);
//显示转换/隐试转换
//byte myByte = 123;
//int myInt = myByte;
//Console.WriteLine("myInt=" + myInt + ",数据类型为:" + myInt.GetType());
//myByte = (byte)myInt;
//Console.WriteLine("myByte=" + myByte + ",数据类型为:" + myByte.GetType());
//float myfloat = myInt; // 隐式转换
//Console.WriteLine("myfloat=" + myfloat + ",数据类型为:" + myfloat.GetType());
//myInt = (int)myfloat;
//Console.WriteLine("myInt=" + myInt + ",数据类型为:" + myInt.GetType());
//char c = 'a';
//myfloat = c;
//string str = "123";
//int num = Convert.ToInt32(str);
//Console.WriteLine("num=" + num + ",数据类型为:" + num.GetType());
//int valueInt1 = 123456;
//float valueFlo1 = 12.12f;
//double valueDou1 = 12.1212121211212; // int/float/double都可以转换成string
//string str1 = Convert.ToString(valueInt1);
//string str2 = Convert.ToString(valueFlo1);
//string str3 = Convert.ToString(valueDou1);
//Console.WriteLine(str1 + ' ' + str1.GetType());
//Console.WriteLine(str2 + ' ' + str2.GetType());
//Console.WriteLine(str3 + ' ' + str3.GetType());
//枚举
//state enemy1;
//enemy1 = state.Pause;
//if (enemy1 == state.Pause)
//{
// Console.WriteLine(enemy1);
//}
//结构体
//Position structVar;
//structVar.x = 0.1f;
//structVar.y = 0.1f;
//structVar.z = 0.1f;
//Console.WriteLine($"{structVar.x} + {structVar.y} + {structVar.z}" );
//数组的3种创建方式
//int[] scores1 = {35,266,46,58,5,25,6};
//int[] scores2 = new int[10]; //确定长度的数组创建
//int[] scores3 = new int[4] { 10, 20, 30, 40 };
//for (int i = 0; i < scores1.Length; i++) // 数组的遍历
//{
// Console.WriteLine(scores1[i]);
//}
//字符串拆分与遍历
//string str = "www.taikr.com";
//string[] str1 = str.Split('.'); // 拆分字符串,以.为分界线。
//for (int i = 0; i < str1.Length; i++)
//{
// Console.WriteLine($"{str1[i]}");
//}
//字符串常用的3个方法:
//string strUpp = str.ToUpper();
//Console.WriteLine(strUpp);
//string strLow = strUpp.ToLower();
//Console.WriteLine(strLow);
//string res = " stm32 ";
//string resolt = res.Trim(); // 去除字符串前面后面的空格
Console.WriteLine(resolt);
//int[] scores1 = { 35, 266, 46, 58, 5, 25, 6 };
//foreach (var item in scores1) // foreach函数可以遍历字符串也可以遍历数组
//{
// Console.WriteLine(item);
//}
//foreach (var item in resolt)
//{
// Console.WriteLine(item);
//}
//排序:
// 系统提供的快速排序法:
//string str = Console.ReadLine();
//string[] strArray = str.Split(' ');
//int[] numArray = new int[strArray.Length];
//for (int i = 0; i < strArray.Length; i++)
//{
// int temp = Convert.ToInt32(strArray[i]);
// numArray[i] = temp;
//}
//Array.Sort(numArray); // Sort快速排序法
//for (int i = 0; i < numArray.Length; i++)
//{
// Console.Write(numArray[i] + " ");
//}
//Console.WriteLine(add(3, 4)); //函数定义与使用
//参数数组;
//int sumResult = Plus(12, 21, 23, 21, 23, 1);
//Console.WriteLine(sumResult);
//数组参数
//int[] shuzu = { 10, 20, 30, 40, 50, 60 };
//int sumResult = sum(shuzu);
//Console.WriteLine(sumResult);
//结构体函数
//CustomerName myName;
//myName.firstName = "guo";
//myName.lastName = "gangzhi";
Console.WriteLine($"My name is {myName.firstName} {myName.lastName}");
//Console.WriteLine(myName.GetName());
//委托的使用
//MyDelegate deFun;
//deFun = Multiply;
//Console.WriteLine(deFun(3.14, 10));
//deFun = Divide;
//Console.WriteLine(deFun(90 , 9));
//匿名类型
//var var1 = 32;
//Console.WriteLine($"var1={var1},类型为:{var1.GetType()}");
}
}
}
添加项目和启动项目:
添加项目:在 解决方案右键=》添加=》新建项目
设置启动项:在 要启动的应用上右键=》设置启动项目
调试:
一、插入断点:
方法一:光标定位到代码,按下F9键,在此按下F9是取消断点
方法二:在需要添加断点的行首位置,直接单击,在次单击取消断点
(在 断点窗口 可以找到所有的窗口,在这里可以定位断点,删除断点。)
二、监控变量的内容:
方式一:把鼠标指向源代码中的变量名,此时会出现一个工具提示,显示该变量的信息。
方法二:在监视窗口中输入变量的内容。
(在局部变量、即使窗口窗口中不但可以监视变量的值,还可以直接去(内存)修改变量中存储的值)
三、单步执行:
逐过程:一条语句一条语句的执行,不会进入函数。
逐语句:一条语句一条语句的执行,进入函数执行。
异常处理:
一、数组下标标越界异常:
class Program
{
static void Main(string[] args)
{
int[] myArray = { 1, 2, 3, 4 };
int myEle = myArray[4]; //数组下面越界
Console.WriteLine(myEle);
Console.ReadKey();
}
}
当程序走到这一步时,程序会终止掉,然后会抛出(IndexOutOfRangeException:)异常:
二、异常的处理方式:
我们处理异常的语句结构如下(包含了三个关键字try catch finally):
try块: 包含可能出现异常的代码。
catch块: 用来捕捉异常,当代码发生异常,那么异常的类型和catch块中的类型一样的时候,
就会执行catch块,如果catch块的参数不写,表示发生任何异常都执行这个catch块。
(catch语句可以有多个对应不同的错误)
finally块:包含了始终会执行的代码,不管有没有异常产生都会执行。
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
try
{
int[] myArray = { 1, 2, 3, 4 };
int myEle = myArray[4]; //数组下面越界
}
catch (IndexOutOfRangeException e) // catch语句可以有多个对应不同的错误
{
Console.WriteLine(e);
}
finally
{
Console.Write("这句总会执行...");
}
Console.ReadKey();
}
}
}
>:System.IndexOutOfRangeException: Index was outside the bounds of the array.
>: at ConsoleApp2.Program.Main(String[] args)
>: in C:Users98512sourcereposConsoleApp1ConsoleApp2Program.cs:line 12
>:这句总会执行...
三、异常处理典型事例:
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("计算两个数值之和:");
int num1 = 0, num2 = 0;
Console.WriteLine("请输入第一个数字,回车确认");
while (true)
{
try
{
num1 = Convert.ToInt32(Console.ReadLine());
break;
}
catch
{
Console.WriteLine("您输入的不是一个整数,请重新输入");
}
}
Console.WriteLine("请输入第二个数字,回车确认");
while(true)
{
try
{
num2 = Convert.ToInt32(Console.ReadLine());
break;
}
catch
{
Console.WriteLine("您输入的不是一个整数,请重新输入");
}
}
int sum = num1 + num2;
Console.WriteLine($"{num1}+{num2}={sum}");
Console.ReadKey();
}
}
}
>:计算两个数值之和:
>;请输入第一个数字,回车确认
>:12
>;请输入第二个数字,回车确认
>:34
>:12+34=46
四、主动抛出异常:
throw new Exception("抛出异常");
面向对象编程:
面向对象,也叫OOP编程,结构化编程,目的是让编程更清晰。
类的数据和函数称为类的成员:
1、数据成员:
数据成员是包含类的数据——字段,常量和事件的成员。
2、函数成员:
函数成员提供了操作类中数据的某个功能。
(方法、属性、构造方法、析构方法、运算器、索引器)
类的创建:
选择要创建类的应用=》添加=》现有项=》类=》输入类的名称 =》添加
类对象最基本的使用方式:
Program.cs文件: using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Customer customer1 = new Customer(); //初始化需要使用new加上类名
customer1.name = "guogangzhi";
//我们自己定义的类声明的对象,需要先进行初始化
Console.WriteLine(customer1.name);
customer1.Show(); //使用对象中的方法
Console.ReadKey();
}
}
}
Class1.cs文件:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApp2
{
class Customer
{
//数据成员:里面包含了4个字段
public string name;
public string address;
public int age;
public string buyTime;
//函数成员:定义了一个方法
public void Show()
{
Console.WriteLine("名字:" + name);
Console.WriteLine("年龄:" + age);
Console.WriteLine("地址:" + address);
Console.WriteLine("购买时间:" + buyTime);
}
}
}
执行结果:
guogangzhi
名字:guogangzhi
年龄:0
地址:
购买时间:
类对象的规范使用方法:
program.cs文件:
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Login login1 = new Login("郭刚志","解方程85栋4号",18, "programmer");
//初始化需要使用new加上类名
login1.Show(); //使用对象中的方法
Console.ReadKey();
}
}
}
class1.cs文件:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApp2
{
class Login
{
private string name;
private string address;
private int age;
private string job;
public Login(string name,string address,int age,string job)
{
this.name = name;
this.address = address;
this.age = age;
this.job = job;
}
public void Show()
{
Console.WriteLine("名字:" + this.name);
Console.WriteLine("年龄:" + this.age);
Console.WriteLine("地址:" + this.address);
Console.WriteLine("职业:" + this.job);
}
}
}
执行结果:
名字:郭刚志
年龄:18
地址:解方程85栋4号
职业:programmer
this和base关键字:
this可以访问当前类中定义的字段,属性和方法,有没有this都可以访问,
有this可以让IDE-VS编辑器给出提示,
另外当方法的参数跟字段重名的时候,使用this可以表明访问的是类中的字段,
base可以调用父类中的公有方法和字段,有没有base都可以访问,
但是加上base. IDE工具会给出提示,把所有可以调用的字段和方法罗列出来方便选择。
派生类的构造函数:
1、使用时在子类中的构造函数:public 派生类名(派生类参数):base(基类参数)
2、系统调用时先调用父类的构造函数。
在类中定义使用属性(get set方法):
program.cs文件: using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Login login1 = new Login("郭刚志",18,"解方程85栋4号", "programmer");
//初始化需要使用new加上类名
login1.Show(); //使用对象中的方法
login1.Age = 30; //通过Age公有属性设置私有字段(通过set方法)
Console.WriteLine(login1.Age); //通过Age公有属性获取私有字段(通过get方法)
Console.ReadKey();
}
}
}
class.cs文件:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApp2
{
class Login
{
private string name;
private string address;
private string job;
private int age; //私有字段
public int Age //公有属性
{
get //返回age值
{
return age;
}
set //value是系统字段,用于设置age值
{
age = value;
}
}
public Login(string name,string address,int age,string job)
{
this.name = name;
this.address = address;
this.job = job;
}
public void Show()
{
Console.WriteLine("名字:" + this.name);
Console.WriteLine("年龄:" + this.age);
Console.WriteLine("地址:" + this.address);
Console.WriteLine("职业:" + this.job);
}
}
}
执行结果: 名字:郭刚志
年龄:18
地址:解方程85栋4号
职业:programmer
30
继承:
实现继承:
表示一个类型派生于一个基类型,它拥有该基类型的所有成员字段和函数。在实现继承中,
派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定重写某个函数的实现代码。
在需要给现有的类型添加功能,或许多相关的类型共享一组重要的公共功能时,这种类型的继承非常有用。
接口继承:
表示一个类型只继承了函数的签名,没有继承任何实现代码。在需要指定该类型具有某些可用的特性时,
最好使用这种类型的继承。
多重继承:
C#不支持多重继承。而C#准许派生子多个接口。System.Object是一个公共的基类。
using System;
namespace RectangleApplication
{
class Rectangle
{
// 成员变量
protected double length;
protected double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}//end class Rectangle
class Tabletop : Rectangle
{
private double cost;
public Tabletop(double l, double w) : base(l, w)
{ }
public double GetCost()
{
double cost;
cost = GetArea() * 70;
return cost;
}
public void Display()
{
base.Display();
Console.WriteLine("成本: {0}", GetCost());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Tabletop t = new Tabletop(4.5, 7.5);
t.Display();
Console.ReadLine();
}
}
}
执行结果: 长度: 4.5
宽度: 7.5
面积: 33.75
成本: 2362.5
使用接口来实现多重继承:
using System;
namespace InheritanceApplication
{
class Shape
{
public void setWidth(int w)
{
width = w;
}
public void setHeight(int h)
{
height = h;
}
protected int width;
protected int height;
}
// 基类 PaintCost
public interface PaintCost
{
int getCost(int area);
}
// 派生类
class Rectangle : Shape, PaintCost
{
public int getArea()
{
return (width * height);
}
public int getCost(int area)
{
return area * 70;
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle Rect = new Rectangle();
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// 打印对象的面积
Console.WriteLine("总面积: {0}", Rect.getArea());
Console.WriteLine("油漆总成本: ${0}" , Rect.getCost(area));
Console.ReadKey();
}
}
}
执行结果: 总面积: 35
油漆总成本: $2450
方法的重写:
1、虚方法:
把一个基类声明为virtual,就可以在任何派生类中重写该函数:
class MyBaseClass{
public virtual string VirtualMethod(){
return "Method is called in base class";
}
}
在派生类中重写另外一个函数时,要使用override关键字显示声明:
class MyDerivedClass:MyBaseClass{
public override string VirtualMethod(){
return "Method is called in derivedclass.";
}
}
重写之后父类中用virtual定义的方法就不存在了(本例中的MyBaseClass)。
2、隐藏方法(一般不用):
如果签名相同的方法在基类和派生类中都进行了声明,但是该方法没有分别声明为virtual和override,
派生类就会隐藏基类方法。(要使用new关键字进行声明,也可以不写)
基类:
class MyBaseClass{
Public int MyMethod(){
}
}
派生类(在派生类中把基类同名的方法隐藏掉了)
class MyDerivedClass:MyBaseClass{
Public new void MyMethod(){
}
}
如何调用基类中隐藏了的方法:
Enemy boss = new Boss();
boss.Move();//隐藏方法:如果使用子类声明的对象,调用隐藏方法会调用子类的,
如果使用父类声明对象,那么就会调用父类中的隐藏方法。
抽象类:
C#准许把类和函数声明为abstract。抽象类不能实例化,抽象类可以包含普通函数的抽象函数,
抽象函数就是只有函数定义没有函数体。显然,抽象函数本身也是虚拟去构造对象。
abstract class Bird //一个抽象类 就是一个不完整的模板
{
private float speed;
public void Eat()
{
}
Public abstract void Fly();
}
class Crow:Bird //继承抽象类
{
Public override void Fly()//继承抽象类时必须去实现抽象方法。
{
Console.WriteLine("重写抽象方法")
}
}
class Program
{
static void Main(string[] args)
{
Crow crow1 = new Crow(); //正常使用
Crow1.Fly();
Bird bird = new Crow(); //我们可以通过抽象类去声明对象,但不可去构造
Bird.Fly();
}
}
密封类和密封方法:
C#准许把类和重写的方法声明为sealed。
对于类,这个表示不能继承该类;对于重写的方法表示不能重写该方法。
修饰符:
修饰符 语义 应用于 说明
public 公有的 所有类型或成员 任何代码均可访问该项
protected 保护的 类、内嵌类型中的成员 只有派生的类型能访问该项
intemal 内同步 所有类型或成员 只有包含它的程序集中访问该项
private 私有的 类、内嵌类型中的成员 只能在它所属的类中访问该项
new 新的 函数成员 隐藏基类中同名的方法
static 静态的 所有成员 不能用对象访问该修饰符对应的字段
virtual 虚拟的 仅函数成员 该修饰符修饰的函数可以被派生类重写
override 重写 仅函数成员 该修饰符修饰的函数可以重写基类中定义了virtual的函数
abstract 抽象的 仅类、函数成员 定义抽象类、方法。
sealed 密封的 类、重写的方法 表示不能继承该类;对于重写的方法表示不能重写该方法。
extern 外部的 仅静态方法 成员在外部用另一种语言实现
定义和实现接口:
定义接口:
在 应用上右键=》添加=》选择接口=》添加;
不准许提供接口中任何成员的实现方式,一般情况下,接口只能包含方法、属性、索引器和事件的声明。
接口不能有构造函数,也不能有字段,接口也不准许运算符重载。
接口定义中不准许声明成员修饰符,接口成员都是公有的。
public interface IFlyHandleer{
public void Fly();
}
实现接口:
public class Type1Enemy:IFlyHandler{ //继承了IFlyHandler接口
public void Fly() //接口要在派生的类中实现
{
Console.WriteLine();
}
}
泛型:
泛型是什么?
通过参数化类型来实现在同一份代码上操作多种数据类型。
利用"参数化类型"将类型抽象化,从而实现灵活的复用。
泛型类定义、使用:
class ClassA<T>
{
private T a;
private T b;
public ClassA(T a,T b)
{
this.a = a;
this.b = b;
}
public T GetSum()
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
var o1 = new ClassA<string>("www.","baidu.com");
var s = o1.GetSum();
Console.WriteLine(s);
}
}
执行结果: www.baidu.com
泛型方法:
定义泛型方法就是定义一个方法,这个方法的参数的类型可以是不确定的,
当调用这个方法的时候再去确定方法的参数的类型。
class Program
{
public static string GetSum<T,T2,T3,T4>(T a,T b)
{
return a + "" + b;
}
static void Main(string[] args)
{
Console.WriteLine(GetSum<int, int, int, int>(12, 34));
Console.WriteLine(GetSum<double, double, double, double>(12.3, 34.3));
Console.WriteLine(GetSum<string, string, string, string>("stm", "32"));
Console.ReadKey();
}
}
执行结果:
1234
12.334.3
stm32
集合类 列表List:
当我们有很多类型一样的数据的时候,前面我们一般使用数组来进行管理,
但是这样有个缺点就是数组的大小是固定的。如果我们很多类型一样的数据,比如游戏得分,
我们可以集合类来进行管理,比如列表List,我们可以使用列表List很方便的添加数据,
删除数据还有其他队数据的操作。
class Program
{
static void Main(string[] args)
{
//List<int> scoreList = new List<int>();//创建了一个空的列表,
//通过类型后面的<>来表示这个列表存储的数据类型
var scoreList = new List<int>();
//var scoreList = new List<int>(){ 1, 2, 3 };//创建一个列表,里面的初始值有三个分别为1,2,3
scoreList.Add(12);//向列表中添加数据数据
scoreList.Add(45);
Console.WriteLine(scoreList[0]);//根据索引访问数据
//Console.WriteLine(scoreList[2]);//索引不存在的时候,会出现异常
List<int> intlist = new List<int>(10);//创建长度为10的列表,当容量不够用的时候,
//会按照原来容量的2倍进行扩容。
intlist.Capacity = 100;//设置列表的容量为100;
Console.ReadKey();
}
}
1、列表内部数据是使用数组进行的存储,一个空的列表内部会有一个长度为0的数组,
当给列表中添加元素的时候,列表的容量会扩大为4,如果添加第5个的时候,列表的大小会重新设置为8,
如果添加第9个元素,列表容量会扩大为16,依次增加。当列表的中的容量发生改变的时候,
它会创建一个新的数组,使用Array.Copy()方法将旧数组中的元素复制到新数组中。
为了节省时间,如果事先知道要存储的数据的个数,就可以利用列表的构造函数指定列表的容量大小,
比如下面的:
List<int>intlist = new List<int>(10);
//创建了一个初始容量为10的列表,当容量不够用的时候,每次都会按原来容量的2倍进行扩容。
我们可以通过Capacity属性获取和设置容量
Intlist.Capacity = 100;
2、注意容量和列表中元素个数的区别,容量是列表中用于存储数据的数组的长度通过Capacity获取,列表中的元素是我们添加进去需要管理的数据,通过Count获取。
3、列表的遍历:
1、for循环,遍历所有的索引,通过索引访问列表中的元素:
for(int i = 0;i<list.Count;i++) {
//循环体list[i]
}
2、foreach遍历:
foreach(int temp in list) // 依次取得list中的每一个元素复制给temp,并执行循环体
{
//循环体 temp
}
4、操作列表的属性和方法:
Add() 添加元素;
insert() 插入元素;
Count() 访问元素个数;
RemoveAt() 移除指定位置的元素;
indexOf() 取得一个元素所在列表中的索引位置
LastindexOf() 上面的方法是从前往后搜索,这个是从后往前搜索,搜索到满足条件的就停止上面的方法,如果没有找到指定元素就返回-1
Sort() 对列表中是元素进行从小到大排序
字符串string:
class Program {
static void Main(string[] args)
{
string s = "www.devsiki.com";
int length = s.Length;
//Console.WriteLine(length);
//if (s == "www.devsiki.com")
//{
// Console.WriteLine("相同");
//}
//else
//{
// Console.WriteLine("不相同");
//}
//s = "http://" + s;
//Console.Write(s);
//int res = s.CompareTo("wwwdevsiki.com");
//当两个字符串相等的时候,返回0 当s在字母表中的顺序靠前的时候,返回-1,否者返回1.
//Console.WriteLine(res);
//string newStr = s.Replace('.', '_');
//string newStr = s.Replace("_", "-----");
//把指定的字符转换成指定的字符,或者把指定的字符串换成指定的字符串
//Console.WriteLine(s);
//Console.WriteLine(newStr);
//string[] strArray = s.Split('.');
//foreach(var temp in strArray)
//{
// Console.WriteLine(temp);
//}
//string str = s.Substring(4,2);//从第4位开始取,向后取2位
//Console.WriteLine(str);
//string str = s.ToUpper();//全部转换为大写
//Console.Write(str);
string str = s.Trim();//去除字符串前后的空格
Console.WriteLine(str);
//字符串的拼接
string[] str1 = { "stm32", "ggz", "ppt" };
string result = String.Join("/",str1);
Console.WriteLine(result);
}
}
StringBuilder类:
1、创建StringBuilder对象:(说明:需要调用System.Text命名空间)
//第一种创建方式:
StringBuilder sb = new StringBuilder("www.devsiki.com");
//第二种创建方式:
StringBuilder sb = new StringBuilder(20);
//第三种创建方式:
StringBuilder sb = new StringBuilder("www.devsiki.com",100);
关于StringBuilder对象创建的时候的内存占用
2、Append()方法,给当前字符串追加一个字符
3、insert()追加特定格式的字符串
4、Replace()从当前字符串中删除字符
5、Replace()在当前字符串中,用某个是字符或者字符串全部替换另外一个字符或者字符串
6、ToSting()把当前stringBuilder中存储的字符串,提取成一个不可变的字符串
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder("www.devsiki.com", 100);
sb.Append("/xxx.html");
//当我们需要对一个字符串进行频繁的删除添加操作的时候,使用StringBuilder的效率比较高
Console.WriteLine(sb.ToString());
//string s = "www.devsiki.com";
//s = s + "/xxx.html";
//Console.WriteLine(s);
}
}
正则表达式:
Regular Expression(正则表达式)用于解决程序中的文本检索,匹配等问题,
正则表达式语言是一种专门用于字符串处理的语言。
你可以认为正则表达式表述了一个字符串的书写规则,
判断用户输入的密码是否合法,判断用户输入的邮箱格式是否合法。
一、常用的操作正则表达式的方法和委托:
下面学习一下位于Ststem.Text.RegularExpressions下的Regex类的一些静态方法和委托
1、静态方法IsMatch(返回值是一个布尔类型,用于判断指定的字符串是否与正则表达式字符串匹配,它有三个重载方法)
bool IsMatch( 参数: input:要搜索匹配项的字符串。
strsing input, pattern:要匹配的正则表达式模式。 返回结果:如果正则表达式找到匹配项,则为true;否则,为false。
sring pattem);
bool IsMatch( 参数: input:要搜索匹配项的字符串。
string input, pattern:要匹配的正则表达式模式。
string pattern, RegexOptions options); options:枚举值得一个按位组合,这个枚举值提供匹配选项。
返回结果:如果正则表达式找到匹配项,则为true;否则,为false;
bool IsMatch( 参数: input:要搜索匹配项的字符串。 pattern:要匹配的正则表达式模式。 options:枚举值得一个按键组合,这些枚举值提供匹配选项。 matchTimeout:超时间隔,或System.Text.RegularExpressions.Regex.InfiniteMatchTimeout指示该方法不应超时。 返回结果:如果正则表达式找到匹配项,则为true;否则,为false
string input,
string pattern,
RegexOptions options,
TimeSpan matchTimeout);
二、关于参数RegexOptions:
它是一个枚举类型,有以下枚举值
RegexOptions枚举值 内联标志 简单说明
ExplicitCapture n 只要定义了命名或编号的组才捕获
LgnoreCase i 不区分大小写
IgnorePatternWhitespace x 消除模式中的非转义空白并启用由#标记的注释。
MultiLine m 多行模式,其原理是修改了^和$的含义
SingleLine s 单行模式,和MultiLine相对应
内联标志可以更小力度(一组为单位)的定义匹配选项
三、静态方法Matches(system.Text.RegularExpressions)
静态方法Matches,在指定的输入字符串中搜索指定的正则表达式的所有匹配项。跟上面方法不同之处,就是这个方法返回的是所有匹配项,他同样有三个重载方法,并且参数和Match方法完全相同
MatchCollection Matches(string input,string pattern);
MatchCollection Matches(string input,string pattern,RsgexOptions options);
MatchCollection Matches(string input,string pattern,RegexOptions options,TimeSpan matchTimeout);
四、Replaces函数(System.Text.RegularExpressions):
我们知道正则表达式主要是实现验证,提取分割,替换字符的功能,Replace函数是实现替换功能的。
1、Replace(string input,strsing pattern,string replacement)
//input是原字符串,pattern是匹配的条件,replacement是替换的内容,就是把符合匹配条件pattern的内容转换成它
比如string result = Regex.Replace("abc","ab","##");
//结果是##C,就是把字符串abc中的ab替换成##
2、Replace(string input,string pattern,string replacement,RegexOptions optios)
//RegexOptions是一个枚举型,用来做一些设定。
//前面用注释时就用到了RegexOptios.lgnorePatternWhitespace.如果在匹配时忽略大小写就可以用RegexOptios.lgnoreCase
比如string resule = Regex.Replace("ABc","ab","##",RegexOptios.lgnoreCase);
如果是简单的替换用上面两个函数就可以实现了,但如果有些复杂的替换,比如匹配到很多内容要替换成不同的字符,就需要用到下面两个函数。
五、静态方法split拆分文本:
使用正则表达式匹配的位置,将文本拆分为一个字符串数组,同样有三个重载方法,返回值为字符串数组
string[] Split(string input,string pattern);
String[] Split(string input,string pattern,RegexOptios optios);
String[] Split(string input,string pattern,RegexOptios optios,TimeSpan matchTimeout);
六、@符号:
我们经常在正则表达式字符串前面加上@字符,这样不让编译器去解析其中的转义字符,而作为正则表达式的语法(元字符)存在。
string s = @"www.baidu.com n lkjsdflkj";
七、定位元字符:
我们经常在正则表达式字符串前面加上@字符,这样不让编译器去解析其中的转义字符,
而作为正则表达式的语法(元字符)存在。
字符 说明
b 匹配单词的开始或结束
B 匹配非单词的开始或者结束
^ 匹配必须出现在字符串的开头或行的开头
$ 匹配必须出现在以下位置:字符串结尾、字符串结尾处的n之前或行的结尾。
A 指定匹配必须出现在字符串的开头(忽略Multiline选项)。
z 指定匹配必须出现在字符串的结尾(忽略Muliline选项)。
Z 指定匹配必须出现在字符串的结尾或字符串结尾处的n之前(忽略Multiline选项)。
G 指定匹配必须出现在上一个匹配结束的地方。与Match.NextMatch()一起使用时,此断言确保所有匹配都是连续的
定位元字符示例:
示例一:区域开始^
String str = "I am Blue cat";
Console.WriteLine(Regex.Replace(str,"^","准备开始"));
>:准备开始I am Blue cat
示例二:区域结束$
string str = "I am Blue cat";
Console.WriteLine(Regex.Replace(str,"$","结束了"));
>:结束了I am Blue cat
基本语法元字符:
字符 说明
. 匹配除换行符以外的任意字符
w 匹配字母、数字、下划线、汉字 (指大小写字母、0-9的数字、下划线_)
W w的补集(除"大小写字母、0-9的数字、下划线_"之外)
s 匹配任意空白符(包括换行符/n、回车符/r、制表符/t、垂直制表符/v、换行符/f)
S s的补集(除s定义的字符之外)
d 匹配数字(0-9数字)
D 表示d的补集(除0-9数字之外)
在正则表达式中,是转义字符.*是元字符 如果要表示一个.*字符的话,需要使用 . *
示例一:效验只准许输入数字
string strCheckNum1 = "23423423a",strCheckNum2="324234"; Console.WriteLine("匹配字符串"+strCheckNum1+"是否为数字:"+Regex.IsMatch(strCheckNum1,@"^d*$")) Console.WriteLine("匹配字符串"+strCheckNum2+"是否为数字:"+Regex.IsMatch(strCheckNum2,@"^d*$"))
示例二:效验只准许输入除大小写字母、0-9的数字、下划线-以外的任何字
string strCheckStr1="abcds_a",strCheckStr2="**&&(((2",strCheckStr3="**&&(((";
string regexStr =@"^W"*$"; Console.WriteLine("匹配字符串"+strCheckStr1+"是否为除大小写字母、0-9的数字、下划线_以外的任何字符:"+Reex.IsMatch(strCheckStr1,regexStr)); Console.WriteLine("匹配字符串"+strCheckStr2+"是否为除大小写字母、0-9的数字、下划线_以外的任何字符:"+Reex.IsMatch(strCheckStr2,regexStr)); Console.WriteLine("匹配字符串"+strCheckStr3+"是否为除大小写字母、0-9的数字、下划线_以外的任何字符:"+Reex.IsMatch(strCheckStr3,regexStr));
八、反义字符:
字符 说明
W w的补集(除"大小写字母、0-9的数字、下划线_"之外)
S s的补集(除s定义的字符之外)
D 表示d的补集(除0-9数字之外)
B 匹配不是单词开头或结束的位置
[ab] 匹配中括号中的字符
[a-c] a字符到c字符之间是字符
[^X] 匹配除了x以外的任意字符
[^adwz] 匹配除了adwz这几个字符以外的任意字符
示例:查找除ahou这之外的所有字符:
string strFind1 = "I am a Cat!",strFind2 = "My Name's Blue cat";
Console.WriteLine("除ahou这个之外的所有字符,原字符为:"+strFind1+
"替换后:"+Regex.Replace(strFind1,@"[^ahou]","*")); Console.WriteLine("除ahou这之外的所有字符,原字符为:"+strFind2+
"替换后:"+Regex.Replace(strFind2,@"[^ahou]","*"));
九、重复描述字符:
字符 说明
{n} 匹配前面的字符n次
{n,} 匹配前面的字符n次或多于n次
{n,m} 匹配前面的字符n到m次
? 重复零次或一次
+ 重复一次或更多次
* 重复零次或更多次
示例:效验输入内容是否为合法QQ号(备注:QQ号为5-12位数字)
string isQq1 = "12333",isQq2="a1233",isQq3="0123456789123",isQq4="556878544";
string regexQq = @"^d{5,12}$";
Console.WriteLine(isQq1 + "是否为合法QQ号(5-12位数字):"+Regex.IsMatch(isQq1,regexQq));
Console.WriteLine(isQq2 + "是否为合法QQ号(5-12位数字):"+Regex.IsMatch(isQq2,regexQq));
Console.WriteLine(isQq3 + "是否为合法QQ号(5-12位数字):"+Regex.IsMatch(isQq3,regexQq));
Console.WriteLine(isQq4 + "是否为合法QQ号(5-12位数字):"+Regex.IsMatch(isQq4,regexQq));
十、择一匹配:
字符 说明
| 将两个匹配条件进行逻辑"或"(Or)运算
示例一:查找数字或字母
string findStr1 = "ad(d3)-df"; string regexFindStr = @"[a-z]|d"; string newStrFind = String.Empty; MatchCollection newStr =Regex.Matches(findStr1,regexFindStr); newStr.Cast<Match>().Select(m=>m.Vaue).ToList<string>().ForEach(i=>newStrFind+=i); Console.WriteLine(findStr1+"中的字母和数字组成的新字符串为:"+newStrFind);
示例二:将人名输出("zhangsan;lisi,wangwuzhaoliu")
string strSplit = "zhangsan;lisi,wangwu.zhaoliu"; string regexSplitstr = @"[;][,][.]"; Regex.Split(strSplit,regexSplitstr).ToList().ForEach(i=>Console.WriteLine(i));
示例三:效验国内电话号码
(支持三种写法校验 A.010-87654321 B.(010)87654321 C.01087654321 D.010 87654321)
string TelNumber1 = "010-87654321",TelNumber2 = "(010)87654321",TelNumber3 = "01087654321", TelNumber4 = "09127654321",TelNumber5 = "010)87654321",TelNumber6 = "(010-87654321", TelNumber7 = "91287654321"; Regex.RegexTelNumBer3 = new Regex(@"(0d{2,3})[-]?d{7,8}|^0d{2,3}[-]?d{7,8}$"); Console.WriteLine("电话号码"+TelNumBer1+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer1)); Console.WriteLine("电话号码"+TelNumBer2+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer2)); Console.WriteLine("电话号码"+TelNumBer3+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer3)); Console.WriteLine("电话号码"+TelNumBer4+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer4)); Console.WriteLine("电话号码"+TelNumBer5+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer5)); Console.WriteLine("电话号码"+TelNumBer6+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer6)); Console.WriteLine("电话号码"+TelNumBer7+"是否合法:"+RegexTelNumber3.IsMatch(TelNumBer7));
十一、对正则表达式的分组:
用小括号来指定子表达式(也叫做分组):
示例一:重复单字符 和 重复分组字符
Console.WriteLine("请输入一个任意字符串,测试分组:") string inputStr = Console.ReadLine(); string StrGroup1 = @"a{2}"; Console.WriteLine("单字符重复2次替换为22,结果为:"+Regex.Replace(inputStr,strGroup1,"22")); //重复 多个字符 使用(abcd){n}进行分组限定 string strGroup2 = @"a{2}"; Console.WriteLine("分组字符重复2次替换为5555,结果为:"+Regex.Replace(inputStr,strGroup2,"5555"));
示例二:效验IP4地址(如:192.168.14,位四段,每段最多三位,每段最大数字255,并且第一位不能为0)
string reexStrlp4 = @"^((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?))$"; Console.WriteLine("请输入一个IP4地址:") string inputStrip4 = Cousole.ReadLine();
Console.WriteLine(inputStrlp4+"是否为合法的IP4地址:"+Regex.IsMatch(inputSrtlp4,regexStrlp4)); Console.WriteLine("请输入一个IP4地址:") string inputSrtlp4Second=Console.ReadLine();
Console.WriteLine(inputStrlp4+"是否为合法的IP4地址:"+Regex.IsMatch(inputStrlp4Second,regexStrlp4));
c# 去除转义符号_C#软件开发基础
最新推荐文章于 2021-06-29 17:22:07 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)