c#个人向总结

c#个人向简单总结


前言:由于博主了解过c,java,c++,所以下面在总结时会略过相似的,只总结了自己不熟的部分


文章目录

入门level1

输入与输出

c# 复制代码
#region//折叠,中间放内容
    
Console.WriteLine("helloworld");//输出
Console.ReadLine();//输入

#endregion

基础变量

c# 复制代码
sbyte, int, short, long//有符号
byte, uint, ushort, ulong//无符号
float, double, decimal//浮点数,隐式转换中的decimal不能存其他两个浮点数
bool, char, string//其他,char为2字节

强转方式

  • c语言同款括号()直接转
  • int.Parse(要转的内容)
  • Convert.ToXXX(要转的内容),XXX为具体的类型

控制台进阶

c# 复制代码
Console.ReadKey(true).keyChar;//常用于不显示在控制台的单字符获取
Console.Clear();//清空控制台
Console.SetWindowSize(x, y);//设置窗口大小
Console.SetBufferSize(x, y);//设置窗口缓冲区大小
Console.SetCursorPosition(x, y);//设置光标位置
Console.ForegroundColor = ConsoleColor.Red;//设置文字颜色,Red可替换
Console.CursorVisible = false;//光标显示隐藏
Enviroment.Exit(0);//关闭控制台

随机数使用

Randomnew一个变量r,随后用r.Next(x. y)=》随机生成一个x(包含)到y(不包含)间的数

基本level2

数组

c# 复制代码
int[] a;//一维
a.length;//获取长度

int[,] a;//二维(真反人类。。)
a.Getlength();//参数为0时获取行长度,为1时获取列长度

int[][] a;//交错,意思是列的长度不固定,行的长度固定(你不是有两个括号的吗,就不能把上面那个改成交错这个改成二维吗。。。)
//获取行的长度时与二维数组一致,但获取列的长度时与一维数组一致,其实这样获取可以推测他底层的实现了。。。

函数

  • 传实参修饰符
    • ref:必须在传入前初始化
    • out:必须在函数内部进行赋值
  • 变长参数params
  • 可以给参数赋默认值,并且函数存在重载

核心level3

垃圾回收机制GC

简要理解

C#中采用分代算法,将内存分为0代1代2代内存

其中大部分新分配内存的对象都会放在0代内存中,当0代内存分配满后,GC会开始检查每个分配的对象上是否有标记可达 (还在用,比如说还有引用指向堆中的对象,则视为可达),若不可达,则将这些不可达的视为垃圾释放,而可达的则会搬迁到1代内存

同样,如果1代内存满了,则会进行相同的过程,不同的是,此时0代也会一起释放

而为了避免过于频繁地触发GC,大对象(80多kb以上)创建时会直接放到2代内存中

手动触发

GC.Collect(),通常用于场景切换时手动释放,避免在游戏过程中触发GC让玩家感到卡顿

类class

成员属性:保护成员变量
c# 复制代码
class Test{
    public Name{
        get;//写方法体时需要return
        set;//写方法体时关键字value表示传入内容
    }//内部两个方法可以通过添加访问修饰符达到只能读不能改的效果
}
构造函数

构造函数可以在后跟上:调用其他构造函数进行一部分初始化内容

c# 复制代码
class Test{
    int age;
    int height;
    Test() {
        age = 0;
    }
    Test(int height):Test() {
        this.height = height;//this和常见语言中一样,指类自己
    }
}
索引器
c# 复制代码
class Test{
    int[] a;
    Test() {
        a = new int[30];
    }
    
    public int this[int i] {
        return a[i];
    }
}

可以在外部使用类名[x]直接赋值

分布partial

修饰类时可以分开几部分写一个类,不能有重复成员,访问修饰符要一致

修饰方法时可一边声明一边实现

类和结构体的比较
  • 结构体是个值对象,在栈区;类是个引用对象,在堆区
  • 结构体不能用protected修饰符,不能给成员变量赋初值,不能自己写无参构造,而类没有这三点限制
  • 基于上面这三点,自然,结构体有了有参构造后无参构造不会被顶掉,且在有参构造中必须初始化所有成员,而类这样做会顶掉无参,不用一次性初始化所有成员
  • 因为结构体在栈区,所以它没有析构函数,没有静态,类有
  • 结构体不能继承结构体,但是可以继承接口
  • 结构体不能将自己的struct作为成员,类可以这样做(但这样声明自己有点吓人了,一不小心就无限递归爆栈了)

选择:数据集合和经常要改变赋值但原对象不想变的可以用struct,要继承多态的用class

静态static

static和const的区别

const常量必须初始化且不能更改,只能修饰变量,不能写在访问修饰符前,static没有这些限制

静态构造函数
  • 不能有访问修饰符和参数
  • 只调用一次,主要用于初始化静态成员
  • 普通类也可以有
拓展方法:写在静态类中的一个静态方法

主要用于为非静态类型添加方法

c# 复制代码
public static void Develop(this int value, 参数1, 参数2, ...) {}
//此例是为int类添加一个叫做Develop的方法,this必须写在第一个正是参数前,this后跟着要添加方法的类
运算符重载operator:一定为公共静态方法
  • 条件运算符要成对实现 ,比如重载了==就必须同时重载!=
  • 不能用refout
c# 复制代码
public static 返回值 operator 运算符(参数){}
//书写规则与c++一致

继承

用法与c++一致,直接子类:父类,不过又和Java一样是单继承(。。。。)

is和as关键字

is用于判断对象,as用于转换对象(比如里氏替换遍历时遇到父类装子类对象,要调用子类特有的方法,可使用as

密封sealed

修饰类时即不允许继承该类

修饰从父类重写的方法时不让自己的后代再重写

多态vob = 虚函数virtual + 重写override + 父类指针base

virtualoverride配合使用,子类可重写父类中的虚函数,重写后想用父类中的该方法可用base调用

抽象abstract和接口interface

abstract修饰的类即抽象类不能实例化,和Java一样可以多继承接口

抽象类和接口的比较

相同点:

  • 都可以被继承,都不能实例化
  • 都可以由方法的声明,子类必须实现其未实现的方法
  • 都遵循多态

不同点:

  • 前者有构造函数,后者无
  • 前者单继承,后者多继承
  • 前者可以有成员变量,后者不行
  • 前者可以声明成员方法,虚方法,抽象方法以及静态方法,后者只能声明抽象方法
  • 前者的方法随便写访问修饰符,后者建议不写,默认未公共

选择:表对象选前者,行为拓展用后者

抽象方法和虚方法的比较

最主要区别:虚方法子类可选择性重写,抽象方法(相当于c++里的纯虚方法=0)子类必须重写

万物之父Object

  • 成员方法GetType():后面说,反射的重点
  • 成员方法MemberwiseClone():浅拷贝,返回新的对象(其内部的引用对象成员与老对象一致)
  • 虚方法toString():可以自己实现一个,但大多数情况没必要
  • 虚方法Equals():不重新实现它就是静态方法,默认比较是否为同一引用,如果要自定义比较就是虚方法(。。。)

Object存值为装箱,把其内值取出来as了为拆箱,多态的最大受益者

插曲提一嘴:StringBuilder比起String效率上的优势,主要在于修改而不是创建,会自动扩容,要用的时候再查提供的方法

进阶level?

泛型<>

和Java那个几乎没区别

泛型约束where

顾名思义,限制泛型修饰的范围,放在后面就行

c# 复制代码
class Test<T> where T:class{}

这个where后面的class可以替换来限制不同类型,可以一次写几个也没关系,如果有多个泛型多写几个where也可以

值类型:struct;引用类型:class;存在公共无参构造函数new()

某个类或者它娃:类名;某个接口或者它娃:接口名;另一个泛型类型或派生:另一个泛型字母

协变out与逆变in

也是修饰泛型的,限制泛型作用的地方

协变out:修饰后的泛型只能作为返回值

逆变in:修饰后的泛型只能作为参数

除此之外,协变是和谐的变化,逆变不和谐,协变修饰后是正常的父类装子类,遵循里氏替换,而被逆变修饰后子类可以去装父类

数据结构(容器?)

  • ArrayList:本质为Object数组
  • HashTable:哈希表,本质同上
  • StackQueue:不用泛型的时候本质同上,用泛型的重载时本质是泛型数组
  • List:本质为泛型数组
  • Dictionary:字典,本质同上
  • LinkedList/LinkedListNode:本质为泛型双向链表,可以从字面意思上看出是有头和身子区分的

委托delegate

装函数名的,用invoke()方法调用或者直接()也行,函数指针的包装版(太掉价了。。。)

自定义委托在一个正常的函数声明前加delegate即可

可以做加减法运算,装多个函数,调用时一起调用,也可以清空

系统自带委托
  • Action:无参无返回值
  • Func<T>:无参有返回值
  • Action<T,...>:有参无返回值(泛型指定参数)
  • Func<T,T,...>:有参有返回值(第一个泛型仍为返回值)
事件event

和委托一个效果,但是更安全,在委托外面再包装一层,定义时public event 定义好的委托名 事件名

  • 只能在类,接口,结构体中定义
  • 不允许外部赋值调用
匿名函数与lambda表达式

通常和委托配套使用

c# 复制代码
//匿名函数
Action a = delegate(){函数逻辑};
//lambda表达式
Action a = (参数)=>{函数逻辑};
List自定义排序
  • 法一:要排序的类继承IComparable接口,实现其中的CompareTo()方法(以类的自定义为例,通常需要传入另一个类作为other与本类this比较)

  • 法二:使用List自带的Sort方法重载,传入逻辑比较函数

    c# 复制代码
    list.Sort((a, b)=>{return a.id > b.id ?1 : -1;});
多线程Thread
c# 复制代码
Thread t = new Thread(要开线程的函数);
//线程方法
t.Start();//开启线程
t.isBackground = true;//后台运行
Thread.Sleep(时间);//线程休眠
lock(obj){逻辑}//obj为任意Object对象,其他也可以,在不同线程内加入lock关键字,可以让线程达到交替执行的效果

反射

运行中获取程序集(源文件内容)

Type类

获取Type

  • Object万物之父类中的方法GetType()
  • typeof(类名)关键字
  • 通过类名Type.GetType("哪个命名空间里的类名")

获取对象里的信息:

c# 复制代码
Type t = typeof(Test);
MemberInfo[] x = t.GetMembers();//获取所有公共成员
ConstructorInfo[] x = t.GetConstructors();//获取所有构造函数
FieldInfo[] x = t.GetFields();//获取所有公共成员变量
MethodInfo[] x = t.GetMethod();//获取所有公共方法

//获取某个具体的成员变量时,把后面的s后缀去掉即可,()内填要获取成员的字符串随后可通过GetValue()和SetValue()方法直接操控值

//获取某个具体的成员方法时,除了和上面一样,若存在重载还需传第二个参数new Type[]{参数列表的type},获取完毕执行时用Invoke()方方法,静态方法参数传null,非静态第一个参数填要执行这个方法的对象,第二个参数new object[]{参数列表}

获取对象:

c# 复制代码
//三步走:要得到哪个构造函数=》实例化上面得到的构造函数得到object对象=》as后获取最终对象
ConstructorInfo x = t.GetConstructor(new Type[]{});//获得无参构造
//若要获取有参构造,在{}内填写要获取构造函数的参数type
object obj = x.Invoke(null);//有参构造时传入参数即可,这一步为实例化获取对象
Test test = obj as Test;
//当然上面两步也可以简写为一步
Test obj = x.Invoke(null) as Test;
Activator类

Type中获取对象的方法太麻烦了,所以有这个一步到位的快速实例化

c# 复制代码
Test obj = Activator.CreateInstance(typeof(Test), 参数列表) as Test;
Assembly程序集类

加载程序集:

c# 复制代码
//加载同一文件下
Assembly assembly = Assembly.Load("程序集名称");
//加载不同文件下
Assembly assembly = Assembly.LoadFrom("包含程序集的文件名称或路径");
Assembly assembly = Assembly.LoadFile("要加载文件的完全限定路径");

//assembly有GetType("类名")方法

有了程序集后就可以用TypeActivator部分的知识实例化对象了

特性[]

Java的注解,为元数据添加额外信息

自定义特性需要定义一个类去继承Attribute

特性相关方法
c# 复制代码
Type t = typeof(Test);
t.IsDefined(typeof(特性名), false);//是否使用特性,第二个参数为是否搜索后代
object[] x = t.GetCustomAttributes(true);//获取所有特性
系统自带特性
  • 限制使用范围[AttributeUsage(AttributesTargets.Class, AllowMultiple = true, Inherited = true)]:三个参数依次为能用的地方(若要加多个能用的地方,使用|连接),是否允许多个特性用在一个目标上,特性能否被后代继承
  • 过时[Obsolete("提示信息", true)]:第二个参数为true时报错,false时警告
  • 条件编译[Conditional("函数名")]:只有define过该函数,调用该函数时才会执行
  • 调用者信息[Caller]:包括[CallerFilePath][CallerLineNumber][CallerMemberName],报错时报的更清楚
  • 外包调用[DllImport]:标记的函数说明它在一个外部的DLL中定义

迭代器iterator

foreach的底层实现,比方说foreach(int i in list),就会先通过GetEnumerator方法获取IEnumerator,再执行其中的MoveNext方法,返回为true则获取Current赋值给i

自定义迭代器实现需继承IEnumberableIEnumerator两个接口,并实现下面四个方法(示例)

c# 复制代码
class Test:IEnumberable, IEnumerator {
    
    public int position = -1;//模拟光标
    private int[] list;
    
    public Test() {
        list = new int[]{1, 2, 3};
    }
    
    public IEnumerator GetEnumerator() {
        Reset();
        return this;
    }
    public object Current{
        get {
            return list[position];
        }
    }
    public bool MoveNext() {
        position++;
        return position < list.Length;
    }
    public void Reset() {
        position = -1;
    }
}

或者除了上面基于基本原理的实现,还可以使用yield语法糖实现,仅需实现一个方法(挺奇妙的)

c# 复制代码
public IEnumerator GetEnumerator() {
        for (int i = 0; i < list.Length; i++) {
            yield return list[i];
        }
}

其他语法

  • var用于偷懒
  • 形如python的内嵌字符串Console.WriteLine($"{name},{age}")
  • 奇怪的?语法糖,比如int? a = null是合法的(真的有正常人这么写吗),见到再查吧

完结撒花,谢谢你的阅读么么叽

参考或者说学习来源:b站唐老狮

相关推荐
海外住宅ip供应商-luck2 分钟前
PHP如何搭建设置代理http并加密使用?
开发语言·http·php
南玖yy15 分钟前
Python 的未来:在多元变革中持续领跑
开发语言·python
南隅。23 分钟前
【C++】基础3——正则表达式,静态多态(函数重载和模板),异常处理
开发语言·c++·正则表达式
乌拉_乌拉_乌拉26 分钟前
C# string字符串介绍
开发语言·c#
JoLonn34 分钟前
PHP中yield关键字的使用
大数据·开发语言·php
C#winform流程图1 小时前
c#winform,倒鸭子字幕效果,typemonkey字幕效果,抖音瀑布流字幕效果
开发语言·c#
摸鱼码1 小时前
(头歌作业—python)3.2 个人所得税计算器(project)
开发语言·python
狐凄1 小时前
练习题:110
开发语言·python·算法
YJlio2 小时前
C盘清理技巧分享:PE & Dism++ 空间清理篇
c语言·开发语言
DanmF--2 小时前
Unity中UDP异步通信常用API使用
网络·网络协议·unity·udp·c#