一、简介
之前的一个某某某自动化公司,我上班的状态完全属于迷惘状态,天天跑车间测试机器(车间中级技术工人),写代码的量呢也是属于那种两周的活,3天就搞完了。完成任务的情况下,学习一些个人的爱好知识也一直被领导怼。机缘巧合的情况下我离职了。
离职后,有好几个老板跟我说直接过去,给我实习6K,还是一个外企福利比较好,公司规模也挺大,让我忌讳的就是外包!然后我就推掉了。
还有一个老板是之前已经发了offer我推掉了现在又在找我实习5K,我还是推掉了。原因就是和离职的公司是一个类型偏向于自动化的(不符合我个人的发展规划)
于是我就是到了这家公司,聊的技术也有一些,负载均衡,数据库集群,SQL调优,线上项目,Redis缓存,几千万数据分库分表操作。挺符合我个人发展规划的!
实习一个月考核转正了!说实话,时间太短,业务还是不够透彻!估计凉凉!
二、转正考核C# 基础知识
3月23号转正考核,这是我考核前整理的学习心得,帮助自己的同时,也想帮助一些在校的学生接触的知识是偏公司的!而不是学校的基础。
装箱和拆箱
装箱:值类型转引用类型 拆箱:引用类型转值类型,拆箱前必须要有装箱过程
+的作用有哪些
做运算符,拼接字符串。+会导致隐式转换,所以使用时应注意
涉及到了转换我们可以聊一下显式类型转换以及隐式类型转换
显式转换以及隐式转换
隐式类型转换 这些转换是 C# 默认的以安全方式进行的转换, 不会导致数据丢失。例如,从小的整数类型转换为大的整数类型,从派生类转换为基类。
显式类型转换 显式类型转换,即强制类型转换。显式转换需要强制转换运算符,而且强制转换会造成数据丢失。
换句话说(白话文) 显式 double8个字节转int4个字节会造成数据丢失,比如double(5.6666)转int会变成5造成丢失了0.6666.这就是显式转换也称为强制转换。 隐式 int4个字节转double8个字节可以直接使用,int(5)转double会变成double(5)有可能5后面还有几个0呢 精度变高了呢!
this和super的区别
this 代表的是本类对象的引用,谁调用,就代表谁; super代表的是父类存储空间的标识(可以理解成父类的引用,可以操作父类的成员)
简单明了!
送分题break,continue,return区别
return 跳出此语句块break 跳出本次循环,执行下面的语句,只能跳出一层循环continue 跳出本次循环执行下次循环
值类型和引用类型
存储方式 值类型存储在内存栈中,引用类型存储在内存堆中,地址存放在内存栈中 ①引用类型可以派生出新的类型,而值类型不行,因为值类型是密封的。 ②引用类型可以包含null但是值类型不行 ③引用类型变量的赋值只是复制对象的引用而不复制对象的本身,而将一个值类型变量复制赋给另一个值类型变量时,将复制包含的值
常量和变量的区别
常量为只读的不可更改值,而变量是可以更改值的;声明常量关键字:const
场景:常量用于全局的一些路径一改全改,或者数据库字符串,或者范围的阈值等
变量分全局变量和局部变量。全局一定要少定义!全局很多的话可以考虑利用单例模式统一管理整个项目的全局变量。
常量分静态常量和动态常量。它们有不同的特性,错误的使用不仅会损失效率,还可能造成错误。相比之下,静态常量在速度上会稍稍快一些,但是灵活性却比动态常量差很多。
//静态常量(隐式是静态的) public const int compiletimeConstant = 1; //动态常量 public static readonly runtimeConstant = 1;
事件中两个参数sender,e的作用分别是什么
sender是事件的发起者,e参数是事件对象,事件所携带的信息
举个例子,文本框更改事件,只要数据更改,就算是一个字符,事件立即会进行触发。
事件是一种特殊的委托,事件和委托搭配使用的比较频繁,见下面委托示例!
委托简单介绍一下
普及一下:比如生产系统,测试零部件是否合格的,不管是按工序测量还是按零件测量都需要很强的数据实时更改需求,所以这里可以考虑利用单例模式管理整个项目的委托事件触发 例如
private static SysRuntime runTime; public static SysRuntime GetInstance() { if (runTime == null) runTime = new SysRuntime(); return runTime; } #region 窗口管理代码 /// <summary> /// 窗体状态改变事件 /// </summary> /// <param name="type"></param> /// <param name="index"></param> public delegate void WinDowStaeChange(FormWindowState state); public event WinDowStaeChange OnWinDowStaeChangeed; /// <summary> /// 当窗口大小发送改变时 /// 最大化不会触发次事件 /// </summary> /// <param name="frmname">目标窗体名称</param> /// <param name="w">宽度</param> /// <param name="h">高度</param> public delegate void WinDowSizeChange(string frmname, int w, int h); public event WinDowSizeChange OnWinDowSizeChangeed; /// <summary> /// 子窗体位置发生改变 /// </summary> /// <param name="point">最新位置</param> public delegate void WinDowLocationChange(string frmname, Point point); public event WinDowLocationChange OnWinDowLocationChangeed; /// <summary> /// 子窗体关闭时 /// </summary> /// <param name="frmname"></param> public delegate void WinDowClose(string frmname); public event WinDowClose OnWinDowClosed;
Lambda简单介绍一下
overload 重载 override 重写的区别
override 重写与 overload 重载的区别。重载是方法的名称相同。参数或参数类型不同,进行多次重载以适应不同的需要 override 是进行基类中函数的重写。实现多态。
private、protected、pubic、internal修饰符的访问权限
private : 私有成员, 在类的内部才可以访问(只能从其声明上下文中进行访问) protected : 保护成员,该类内部和从该类派生的类中可以访问 public : 公共成员,完全公开,没有访问限制 internal: 在同一命名空间内可以访问
什么是受管制(托管)的代码?
托管代码。运行.NET 公共语言运行时CLR的代码 非托管代码。不经过CLR运行。程序员自行分配和释放内存空间
注意!非托管代码一定要注意内存的问题!
ORM
ORM是一种对象关系映射框架。用于实现面向对象编程语言里不同类型系统的数据之间的转换
建议使用:SqlSugar。
ORM与传统的数据库访问技术相比, 优点:开发效率更高,数据访问更抽象、轻便,支持面向对象封装 缺点:降低程序的执行效率,思维固定化
GC是什么? 为什么要有GC?
GC是垃圾收集器。程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
System.gc() Runtime.getRuntime().gc()
类(class)与结构(struct)的异同?
class分配在内存的堆,可以被实例化,属于引用类型,可以实现接口和单继承其他类,还可以作为基类型。 struct分配在内存的栈,属于值类型,不能作为基类型,但是可以实现接口
string str1 = null 与 string str2 ="" 区别?
string str1 = null 是不给他分配内存空间,因此str1还不是一个实例化的对象 string str2 = "" 给它分配长度为空字符串的内存空间,因此str2已经实例化
String s = new String("xyz");创建了几个String Object?
两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。
abstract class和interface有什么区别?
abstract 声明抽象类抽象方法,一个类中有抽象方法,那么这个类就是抽象类了。所谓的抽象方法,就是不含主体(不提供实现方法),必须由继承者重写。因此,抽象类不可实例化,只能通过继承被子类重写。 interface 声明接口,只提供一些方法规约,不提供任何实现;不能用public、abstract等修饰,无字段、常量,无构造函数
try里的return和final冲突吗?介绍一下
try后的finally {}里的code会被执行,在return前执行。
堆和栈是啥?
上面说了那么多堆那么多栈到底是啥呀。
栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。栈内存无需我们管理,也不受GC管理。当栈顶元素使用完毕,立马释放。而堆则需要GC清理。
堆:一般由程序员分配释放。用new、malloc等分配内存函数分配得到的就是在堆上。堆是无序的,他是一片不连续的内存域,有用户自己来控制和释放,
使用引用类型的时候,一般是对指针进行的操作而非引用类型对象本身。但是值类型则操作其本身。
using和new这两个关键字有什么意义
using 引入名称空间或者使用非托管资源,使用完对象后自动执行实现了IDisposable接口的类的Dispose方法 new 新建实例或者隐藏父类方法
所以为了提升代码的内存性能,在自己掌控的情况下,使用某一库对象之类的可以用using。
进程和线程的区别?
进程是系统进行资源分配和调度的单位; 线程是CPU调度和分派的单位; 一个进程可以有多个线程,这些线程共享这个进程的资源。
DataReader与Dataset有什么区别?
DataReader使用时始终占用SqlConnection,在线操作数据库。任何对SqlConnection的操作都会引发DataReader的异常.因为DataReader每次只在内存中加载一条数据,所以占用的内存是很小的..因为DataReader的特殊性和高性能.所以DataReader是只进的.你读了第一条后就不能再去读取第一条了.。 DataSet则是将数据一次性加载在内存中.抛弃数据库连接.读取完毕即放弃数据库连接.因为DataSet将数据全部加载在内存中.所以比较消耗内存.但是确比DataReader要灵活.可以动态的添加行,列,数据.对数据库进行回传更新操作
启动一个线程用run()还是start()?
启动一个线程用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行,并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
支持多重继承么?
类之间不支持,接口之间支持。类对接口叫做实现,不叫继承。
GC
当程序需要更多的堆空间时,GC需要进行垃圾清理工作,暂停所有线程,找出所有无被引用的对象,进行清理,并通知栈中的指针重新指向地址排序后的对象。
GC只能处理托管内存资源的释放,对于非托管资源则不能使用GC进行回收,必须由程序员手动回收,例如FileStream或SqlConnection需要调用Dispose进行资源的回收。
CLR
公共语言运行库,负责资源管理(包括内存分配、程序及加载、异常处理、线程同步、垃圾回收等),并保证应用和底层操作系统的分离。
序列化与反序列化
序列化:将对象状态转换为可保持或传输的格式的过程。将对象实例的字段及类的名称转换成字节流,然后把字节流写入数据流
反序列化:将流转换为对象。
这两个过程结合起来,可以轻松地存储和传输数据。
参数传递 ref 与 out 的区别
ref指定的参数在函数调用时必须先初始化,而out不用 out指定的参数在进入函数时会清空自己,因此必须在函数内部进行初始化赋值操作,而ref不用
总结:ref可以把值传到方法里,也可以把值传到方法外;out只可以把值传到方法外
注意:string作为特殊的引用类型,其操作是与值类型看齐的,若要将方法内对形参赋值后的结果传递出来,需要加上ref或out关键字。
浅克隆与深克隆(浅拷贝与深拷贝)
下面简单介绍一下浅克隆
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。通过实现ICloneable接口的Clone()方法,并调用MemberwiseClone()方法来实现浅克隆
深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
在C#语言中,如果需要实现深克隆,可以通过序列化(Serialization)等方式来实现。序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作
String与StringBuffer的区别
String 对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值。这样原来的对象就没用了,就要被垃圾回收非常影响性能。
StringBuffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象。它只能通过构造函数来建立。对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中赋值的时候可以通过它的append方法。sb.append("hello");
字符串连接操作中StringBuffer的效率要比String高。StringBuffer 的速度几乎是String 上万倍
类和结构的区别?
前者为引用类型,后者为值类型