跳槽涨薪后一个月考核转正——C# 面试考核基础知识

欢少的成长之路

共 7095字,需浏览 15分钟

 · 2021-03-25

简介:以上文章讲述的是【SQL调优与设计规范】接下来我总结一下【C# 面试考核基础知识】。觉得我还可以的可以加群一起督促学习探讨技术。QQ群:1076570504 个人学习资料库http://www.aolanghs.com/ 微信公众号搜索【欢少的成长之路】

一、简介

之前的一个某某某自动化公司,我上班的状态完全属于迷惘状态,天天跑车间测试机器(类似于车间中级技术工人),写代码的量呢也是属于那种两周的活,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 上万倍

类和结构的区别?

前者为引用类型,后者为值类型

三、总结

这是我目前学习到以及掌握的C# 基础知识!

希望各位读者可以学到一些知识然后提升自己的薪资水平!

广度深度都有,全部原创,有想了解的也可以评论我会一一回复

知道的越多,不知道的就越多。找准方向,坚持自己的定位!加油向前不断前行,终会有柳暗花明的一天!
创作不易,你们的支持就是对我最大认可!
文章将持续更新,我们下期见!QQ群:1076570504 微信公众号搜索【欢少的成长之路】请多多支持!


浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报