C#语言基础-03
写这两篇文章的目的是为了备忘、 C#语言在大学读书时候学过、当时做过一些东西、但是由于从事的主要工作和C#无关便忘记了。 近来公司增加了Unity业务、 写Unity主要是C# 和js 想来C# 的语法结构和Java很相似、于是采用了C#语言作为公司游戏项目的主要语言。
本系列主要分上中下三篇文章来记录。 分别牵涉到C# 中的初级、中级、高级内容。
由于本月一直忙于公司的项目、 所以发文就耽搁了, 但是回想五月忙上过去了,还是整理整理发一篇吧。
本文主要写一些关于C#语言的高级知识, 如果没有看过初级的,可以先看上一篇文章,在电脑上敲敲试试,跑一下看看。
1.string相关操作
class Program {
static void Main(string[] args)
{
string s = "www.samuelnotes.com";//我们使用string类型去存储字符串类型 字符串需要使用双引号引起来
int length = s.Length;
if (s == "www.samuelnotes.com")
{
Console.Write("相同");
}
else
{
Console.Write("不相同");
}
Console.Write(length);
s = "http://" + s;
Console.Write(s);
char c = s[3];
Console.WriteLine(c);
for (int i = 0; i < s.Length; i++)
{
Console.WriteLine(s[i]);
}
//string s = "www.samuelnotes.com";//string 是System.String的别名
//int res = s.CompareTo("saki");//当两个字符串相等的时候,返回0 当s在字母表中的排序靠前的时候,返回-1, 否则返回1
//Console.Write(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);
//Console.WriteLine(str);
//string str = s.ToUpper();
//Console.Write(str);
//string str =s.Trim();
//Console.WriteLine(str);
int index = s.IndexOf("samuelnotesdd");//我们可以使用这个方法判断当前字符串是否包含一个子字符串,如果不包含,返回-1,如果包含会返回第一个字符的索引
Console.WriteLine(index);
Console.ReadKey();
}
}
- stringBuilder
StringBuilder {
class Program {
static void Main(string[] args) {
//1,
//StringBuilder sb = new StringBuilder("www.samuelnotes.com");//利用构造函数创建stringbuilder
//2
//StringBuilder sb = new StringBuilder(20);//初始一个空的stringbuilder对象,占有20个字符的大小
//3
//StringBuilder sb = new StringBuilder("www.samuelnotes.com", 100);
//sb.Append("/xxx.html");
//当我们需要对一个字符串进行频繁的删除添加操作的时候,使用stringbuilder的效率比较高
//Console.WriteLine(sb.ToString());
//sb.Insert(0, "http://");
//Console.WriteLine(sb);
//sb.Remove(0, 3);
//Console.WriteLine(sb);
//sb.Replace(".", "");
//sb.Replace('.', '-');
//Console.WriteLine(sb);
//string s = "www.samuelnotes.com";
//s = s + "/xxx.html";
//Console.WriteLine(s);
Console.ReadKey();
}
}
}
3.正则表达式
class Program {
static void Main(string[] args)
{
//定位元字符 ^ $
//string s = "I am blue cat.";
//string res = Regex.Replace(s, "^", "开始:");//搜索字符串 符合正则表达式的情况,然后把所有符合的位置,替换成后面的字符串
//Console.WriteLine(res);
//string res = Regex.Replace(s, "$", "结束");
//Console.WriteLine(res);
//string s = Console.ReadLine();
//bool isMatch = true;//默认标志位,表示s是一个合法密码(全部是数字)
//for (int i = 0; i < s.Length; i++)
//{
// if (s[i] < '0' || s[i] > '9')//当前字符如果不是数字字符
// {
// isMatch = false;
// break;
// }
//}
//if (isMatch)
//{
// Console.WriteLine("是一个合法密码");
//}
//else
//{
// Console.WriteLine("不是一个合法密码");
//}
//string pattern = @"^\d*$";//正则表达式
//string pattern = @"\d*";
//bool isMatch = Regex.IsMatch(s, pattern);
//Console.WriteLine(isMatch);
//string pattern = @"^\W*$";
//反义字符
//string str = "I am a cat.";
//string pattern = @"[^ahou]";//它代表一个字符, 除了ahou之外的任意一个字符
//string s = Regex.Replace(str, pattern, "*");
//Console.WriteLine(s);
//重复描述字符
//string qq1 = "234234";
//string qq2 = "234234234234234";
//string qq3 = "d4234234234";
//string pattern = @"^\d{5,12}$";
//Console.WriteLine( Regex.IsMatch(qq1,pattern) );
//Console.WriteLine( Regex.IsMatch(qq2,pattern) );
//Console.WriteLine( Regex.IsMatch(qq3,pattern) );
//string s = "34 ((*&sdflkj 路口的设计费";
//string pattern = @"\d|[a-z]";
//MatchCollection col = Regex.Matches(s, pattern);
//foreach (Match match in col)
//{
// Console.WriteLine(match.ToString());//调用tostring方法,会输出match所匹配到的字符串
//}
//string s = "zhangsan;lisi,wangwu.zhaoliu";
string pattern = @"[;,.]";
//string pattern = @"[;]|[,]|[.]";
//string[] resArray = Regex.Split(s, pattern);
//foreach (var s1 in resArray)
//{
// Console.WriteLine(s1);
//}
//重复 多个字符 使用(abcd){n}进行分组限定
string inputStr = Console.ReadLine();
string strGroup2 = @"(ab\w{2}){2}";// == "ab\w{2}ab\w{2}"
Console.WriteLine("分组字符重复2两次替换为5555,结果为:" + Regex.Replace(inputStr, strGroup2, "5555"));
Console.ReadKey();
}
}
- 委托
我们再来看一下委托, 委托的用法很简单,
class Program
{
private delegate string GetAString();//定义了一个委托类型,这个委托类型的名字叫做GetAString
static void Main(string[] args)
{
//int x = 40;
string s = x.ToString();//tostring 方法用来把数据转换成字符串
Console.WriteLine(s);
使用委托类型 创建实例
GetAString a = new GetAString(x.ToString);//a指向了x中的tostring方法
//GetAString a = x.ToString;
string s = a();//通过委托实例去调用 x中的tostring方法
//string s = a.Invoke();//通过invoke方法调用a所引用的方法
//Console.WriteLine(s);//通过委托类型是调用一个方法,跟直接调用这个方法 作用是一样的
//实例2 使用委托类型作为方法的参数
PrintString method = Method1;
PrintStr(method);
method = Method2;
PrintStr(method);
Console.ReadKey();
}
private delegate void PrintString();
static void PrintStr( PrintString print )
{
print();
}
static void Method1() {
Console.WriteLine("method1");
}
static void Method2() {
Console.WriteLine("method2");
}
}
打印输出:
method1
method2
5.委托Action
Action委托 {
class Program {
static void PrintString()
{
Console.WriteLine("hello world.");
}
static void PrintInt(int i)
{
Console.WriteLine(i);
}
static void PrintString(string str)
{
Console.WriteLine(str);
}
static void PrintDoubleInt(int i1, int i2)
{
Console.WriteLine(i1+i2);
}
static void Main(string[] args)
{
//Action a = PrintString;//action是系统内置(预定义)的一个委托类型,它可以指向一个没有返回值,没有参数的方法
//a.Invoke();
Action<int> a = PrintInt;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个int参数的方法
a.Invoke(12312);
//Action<string> a = PrintString;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个string参数的方法 在这里系统会自动寻找匹配的方法
//Action<int, int> a = PrintDoubleInt;
//a(34, 23);
Console.ReadKey();
//action可以后面通过泛型去指定action指向的方法的多个参数的类型 ,参数的类型跟action后面声明的委托类型是对应着的
}
}
}
6.委托Func
Func委托 {
class Program {
static int Test1()
{
return 1;
}
static int Test2(string str)
{
Console.WriteLine(str);
return 100;
}
static int Test3(int i, int j)
{
return i + j;
}
static void Main(string[] args)
{
Func<int> a = Test1;//func中的泛型类型制定的是 方法的返回值类型
Console.WriteLine(a());
Func<string, int> a = Test2;//func后面可以跟很多类型,最后一个类型是返回值类型,前面的类型是参数类型,参数类型必须跟指向的方法的参数类型按照顺序对应
Console.WriteLine(a("xxxx"));
Func<int, int, int> a = Test3;//func后面必须指定一个返回值类型,参数类型可以有0-16个,先写参数类型,最后一个是返回值类型
int res = a(1, 5);
Console.WriteLine(res);
Console.ReadKey();
}
}
}
后边再来个冒泡排序联系一下:
冒泡排序拓展 {
class Program {
static void Sort(int[] sortArray)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
if (sortArray[i] > sortArray[i + 1])
{
int temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
static void CommonSort<T>(T[] sortArray, Func<T,T,bool> compareMethod)
{
bool swapped = true;
do {
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++) {
if (compareMethod(sortArray[i],sortArray[i+1])) {
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
static void Main(string[] args) {
int[] sortArray = new int[] { 123, 23, 12, 3, 345, 43, 53, 4 };
Sort(sortArray);
foreach (var temp in sortArray)
{
Console.Write(temp + " ");
}
//Employee[] employees = new Employee[]
//{
// new Employee("dsf",12),
// new Employee("435dsf",234),
// new Employee("234dsf",14),
// new Employee("ds234f",234),
// new Employee("dssfdf",90)
//};
//CommonSort<Employee>(employees,Employee.Compare);
//foreach (Employee em in employees)
//{
// Console.WriteLine(em);
//}
Console.ReadKey();
}
}
class Employee {
public string Name { get; private set; }
public int Salary { get; private set; }
public Employee(string name, int salary)
{
this.Name = name;
this.Salary = salary;
}
//如果e1大于e2的话,返回true,否则返回false
public static bool Compare(Employee e1, Employee e2)
{
if (e1.Salary > e2.Salary) return true;
return false;
}
public override string ToString()
{
return Name + ":" + Salary;
}
}
7.多播委托
class Program {
static void Test1()
{
Console.WriteLine("test1");
//throw new Exception();
}
static void Test2()
{
Console.WriteLine("test2");
}
static void Main(string[] args) {
//多播委托
Action a = Test1;
//a = Test2;
a += Test2;//表示添加一个委托的引用
//a -= Test1;
//a -= Test2;
//if(a!=null)
// a();//当一个委托没有指向任何方法的时候,调用的话会出现异常null
Delegate[] delegates = a.GetInvocationList();
foreach (Delegate de in delegates)
{
de.DynamicInvoke();
}
Console.ReadKey();
}
}
这样就可以同时调用a所指向所有的方法。
8.匿名方法
namespace 匿名方法 {
class Program {
static int Test1(int arg1, int arg2)
{
return arg1 + arg2;
}
static void Main(string[] args)
{
//Func<int, int, int> plus = Test1;
//修改成匿名方法的形式
Func<int, int, int> plus = delegate(int arg1, int arg2)
{
return arg1 + arg2;
};
//匿名方法 本质上是一个方法,只是没有名字,任何使用委托变量的地方都可以使用匿名方法赋值
Console.ReadKey();
}
}
9.lambda 表达式
namespace _09_Lambda表达式 {
class Program {
static void Main(string[] args) {
//lambda表达式用来代替匿名方法,所以一个lambda表达式也是定义了一个方法
//Func<int, int, int> plus = delegate(int arg1, int arg2) {
// return arg1 + arg2;
//};
Func<int, int, int> plus = (arg1, arg2) =>// lambda表达式的参数是不需要声明类型的
{
return arg1 + arg2;
};
Console.WriteLine(plus(90, 60));
Func<int, int> test2 = a => a + 1;//lambda表示的参数只有一个的时候,可以不加上括号 当函数体的语句只有一句的时候,我们可以不加上大括号 也可以不加上return语句
Func<int, int> test3 = (a) =>
{
return a + 1;
};
Console.WriteLine(test2(34));
Console.WriteLine(test3(34));
Console.ReadKey();
}
}
}
- 事件
namespace 事件 {//Event
class Program
{
public delegate void MyDelegate();
//public MyDelegate mydelgate; //声明了一个委托类型的变量,作为类的成员
public event MyDelegate mydelgate;//声明了一个委托类型的变量,作为类的成员
static void Main(string[] args)
{
Program p = new Program();
p.mydelgate = Test1;
p.mydelgate();
Console.ReadKey();
}
static void Test1()
{
Console.WriteLine("test1");
}
}
}
- 观察者设计者模式
namespace _012_观察者设计模式_猫捉老鼠 {
class Program {
static void Main(string[] args) {
Cat cat = new Cat("加菲猫","黄色");
Mouse mouse1 = new Mouse("米奇","黑色",cat);
//cat.catCome += mouse1.RunAway;
//Mouse mouse2 = new Mouse("唐老鸭", "红色",cat);
//cat.catCome += mouse2.RunAway;
//Mouse mouse3 = new Mouse("xx", "红色",cat);
//cat.catCome += mouse3.RunAway;
Mouse mouse4 = new Mouse("水", "红色",cat);
//cat.catCome += mouse4.RunAway;
//cat.CatComing(mouse1,mouse2,mouse3);//猫的状态发生改变 在cat中调用了观察者的方法,当观察者发生改变的时候,需要同时修改被观察者的代码
cat.CatComing();
//cat.catCome();//事件不能再类的外部触发,只能在类的内部触发
Console.ReadKey();
}
}
}
namespace _011_观察者设计模式_猫捉老鼠 {
/// <summary>
/// 观察者类:老鼠
/// </summary>
class Mouse
{
private string name;
private string color;
public Mouse(string name, string color,Cat cat)
{
this.name = name;
this.color = color;
cat.catCome += this.RunAway;//把自身的逃跑方法 注册进 猫里面 订阅消息
}
/// <summary>
/// 逃跑功能
/// </summary>
public void RunAway()
{
Console.WriteLine(color+"的老鼠"+name+"说: 老猫来, 赶紧跑, 我跑, 我使劲跑,我加速使劲跑 ...");
}
}
}
namespace _011_观察者设计模式_猫捉老鼠 {
/// <summary>
/// 猫类
/// </summary>
class Cat
{
private string name;
private string color;
public Cat(string name, string color)
{
this.name = name;
this.color = color;
}
/// <summary>
/// 猫进屋(猫的状态发生改变)(被观察者的状态发生改变)
/// </summary>
//public void CatComing(Mouse mouse1,Mouse mouse2,Mouse mouse3)
public void CatComing()
{
Console.WriteLine(color+"的猫"+name+"过来了,喵喵喵 ...");
//mouse1.RunAway();
//mouse2.RunAway();
//mouse3.RunAway();
if(catCome!=null)
catCome();
}
public event Action catCome;//声明一个事件 发布了一个消息
}
}
- 反射
namespace _012_反射和特性 {
class Program {
static void Main(string[] args) {
//每一个类对应一个type对象,这个type对象存储了这个类 有哪些方法跟哪些数据 哪些成员
//MyClass my = new MyClass();//一个类中的数据 是存储在对象中的, 但是type对象只存储类的成员
//Type type = my.GetType();//通过对象获取这个对象所属类 的Type对象
//Console.WriteLine(type.Name);//获取类的名字
//Console.WriteLine(type.Namespace);//获取所在的命名空间
//Console.WriteLine(type.Assembly);
//FieldInfo[] array= type.GetFields();//只能获取public 字段
//foreach (FieldInfo info in array)
//{
// Console.Write(info.Name+" ");
//}
//PropertyInfo[] array2 = type.GetProperties();
//foreach (PropertyInfo info in array2)
//{
// Console.Write(info.Name+" ");
//}
//MethodInfo[] array3 = type.GetMethods();
//foreach (MethodInfo info in array3)
//{
// Console.Write(info.Name+" ");
//}
//通过type对象可以获取它对应的类的所有成员(public)
MyClass my = new MyClass();
Assembly assem = my.GetType().Assembly;//通过类的type对象获取它所在的程序集 Assembly
Console.WriteLine(assem.FullName);
Type[] types = assem.GetTypes();
foreach (var type in types)
{
Console.WriteLine(type);
}
Console.ReadKey();
}
}
}
class MyClass
{
private int id;
private int age;
public int number;
public string Name { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
public void Test1() {
}
public void Test2() {
}
}
- 特性
namespace _013_特性 {
//通过制定属性的名字,给属性赋值,这种事命名参数
[MyTest("简单的特性类",ID = 100)]//当我们使用特性的时候,后面的Attribute不需要写
class Program {
[Obsolete("这个方法过时了,使用NewMethod代替")] //obsolete特性用来表示一个方法被弃用了
static void OldMethod()
{
Console.WriteLine("Oldmethod");
}
static void NewMethod()
{
}
[Conditional("IsTest")]
static void Test1() {
Console.WriteLine("test1");
}
static void Test2() {
Console.WriteLine("test2");
}
[DebuggerStepThrough]//可以跳过debugger 的单步调试 不让进入该方法(当我们确定这个方法没有任何错误的时候,可以使用这个)
static void PrintOut(string str,[CallerFilePath] string fileName="",[CallerLineNumber] int lineNumber=0,[CallerMemberName] string methodName ="")
{
Console.WriteLine(str);
Console.WriteLine(fileName);
Console.WriteLine(lineNumber);
Console.WriteLine(methodName);
}
static void Main(string[] args) {
//NewMethod();
//OldMethod();
//Console.ReadKey();
//Test1();
//Test2();
//Test1();
//PrintOut("123");
//
Type type = typeof(Program);//通过typeof+类名也可以获取type对象
object[] array = type.GetCustomAttributes(false);
MyTestAttribute mytest = array[0] as MyTestAttribute;
Console.WriteLine(mytest.Description);
Console.WriteLine(mytest.ID);
Console.ReadKey();
}
}
}
namespace _013_特性 {
//1, 特性类的后缀以Attribute结尾
//2, 需要继承自System.Attribute
//3, 一般情况下声明为 sealed
//4, 一般情况下 特性类用来表示目标结构的一些状态(定义一些字段或者属性, 一般不定义方法)
[AttributeUsage(AttributeTargets.Class)]//表示该特性类可以应用到的程序结构有哪些
sealed class MyTestAttribute : System.Attribute {
public string Description { get; set; }
public string VersionNumber { get; set; }
public int ID { get; set; }
public MyTestAttribute(string des)
{
this.Description = des;
}
}
}
14.总结
还是那句话、多思考、上手敲代码、 调试调试、多试试。 如果有问题可以评论区留言共同学习进步。