c#面试题
1. 重载和重写的区别
1) 所处位置不同重载在同类中重写在父子类中
2) 定义方式不同重载方法名相同参数列表不同重写方法名和参数列表都相同
3) 调用方式不同重载使用相同对象以不同参数调用重写用不同对象以相同参数调用
4) 多态时机不同重载时编译时多态重写是运行时多态
2. 面向对象的三大特点
封装、继承、多态
1.继承:提高代码重用度,增强软件可维护性的重要手段,符合开闭原则。
2.封装:封装是将数据和行为相结合,通过行为约束代码修改数据的程度,增强数据的安全性,属性是C#封装实现的最好体现。
3.多态性:多态性是指同名的方法在不同环境下,自适应的反应出不同得表现,是方法动态展示的重要手段。
3. 简述值类型和引用类型有什么区别
1.值类型存储在内存栈中,引用类型数据存储在内存堆中,而内存单元中存放的
是堆中存放的地址。
2.值类型存取快,引用类型存取慢。
3.值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针和引用。
4.栈的内存是自动释放的,堆内存是.NET 中会由 GC 来自动释放。
5.值类型继承自 System.ValueType,引用类型继承自System.Object。
4. 请简述private,public,protected,internal的区别
public:对任何类和成员都公开,无限制访问
private:仅对该类公开
protected:对该类和其派生类公开
internal:只能在包含该类的程序集中访问该类
protectedinternal:protected + internal
5. C#中所有引用类型的基类是什么
引用类型的基类是 System.Object 值类型的基类是System.ValueType
同时,值类型也隐式继承自 System.Object
6. 请简述ArrayList 和List<Int>的主要区别
ArrayList 不带泛型数据类型丢失
List<T>带泛型数据类型不丢失
ArrayList需要装箱拆箱 List<T>不需要
7. 请简述 GC(垃圾回收)产生的原因,并描述如何避免?
GC 为了避免内存溢出而产生的回收机制
避免:
1)减少 new 产生对象的次数
2)使用公用的对象(静态成员)
8. 请描述Interface 与抽象类之间的不同
1.接口不是类不能实例化抽象类可以间接实例化
2.接口是完全抽象抽象类为部分抽象
3.接口可以多继承抽象类是单继承
1. 请简述关键字Sealed 用在类声明和函数声明时的作用
类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。
1. 反射的实现原理?
可以在加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息
反射即在运行期动态获取类、对象、方法、对象数据等的一种重要手段
主要使用的类库:System.Reflection
核心类:
1.Assembly描述了程序集
2.Type描述了类这种类型
3.ConstructorInfo描述了构造函数
4.MethodInfo描述了所有的方法
5.fieldInfo描述了类的字段
6.PropertyInfo描述类的属性
通过以上核心类可在运行时动态获取程序集中的类,并执行类构造产生类对象,动态获取对象的字段或属性值,更可以动态执行类方法和实例方法等。
1. .Net 与 Mono 的关系?
.Net是一个语言平台,Mono为.Net提供集成开发环境,集成并实现了.NET的编译器、CLR 和基础类库,使得.Net既可以运行在windows也可以运行于 linux,Unix,Mac OS 等。
2. 在类的构造函数前加上 static 会报什么错?为什么?
构造函数格式为 public+类名如果加上 static 会报错(静态构造函数不能有访问修饰符)
原因:静态构造函数不允许访问修饰符,也不接受任何参数;无论创建多少类型的对象,静态构造函数只执行一次;运行库创建类实例或者首次访问静态成员之前,运行库调用静态构造函数;静态构造函数执行先于任何实例级别的构造函数;显然也就无法使用 this 和 base 来调用构造函数。
3. C# String 类型比 stringBuilder 类型的优势是什么?
如果是处理字符串的话,用 string 中的方法每次都需要创建一个新的字符串对象并且分配新的内存地址,而 stringBuilder 是在原来的内存里对字符串进行修改,所以在字符串处理
方面还是建议用 stringBuilder 这样比较节约内存。但是string 类的方法和功能仍然还是比stringBuilder 类要强。
string 类由于具有不可变性(即对一个 string 对象进行任何更改时,其实都是创建另外一个 string 类的对象),所以当需要频繁的对一个 string 类对象进行更改的时候,建议使用StringBuilder类,StringBuilder 类的原理是首先在内存中开辟一定大小的内存空间,当对此 StringBuilder 类对象进行更改时,如果内存空间大小不够,会对此内存空间进行扩充,而不是重新创建一个对象,这样如果对一个字符串对象进行频繁操作的时候,不会造成过多的内存浪费,其实本质上并没有很大区别,都是用来存储和操作字符串的,唯一的区别就在于性能上。
String 主要用于公共 API,通用性好、用途广泛、读取性能高、占用内存小。
StringBuilder 主要用于拼接 String,修改性能好。
不过现在的编译器已经把 String 的 + 操作优化成 StringBuilder 了,所以一般用String 就可以了
String 是不可变的,所以天然线程同步。
StringBuilder 可变,非线程同步。
4. C# 函数 Func(string a, string b)用 lambda 表达式怎么写?
(a,b) => {};
5. 数列1,1,2,3,5,8,13...第 n 位数是多少?用 C#递归算法实现
public int CountNumber(int num)
{
if (num == 1 ||num == 2)
{
return 1;
}
else
{
returnCountNumber(num -1) + CountNumber(num-2);
}
}
1. 冒泡排序(手写代码)
public static voidBubblingSort(int[]array)
{
for (int i = 0;i < array.Length; i++)
{
for (int j =0; j<array.Length– 1-i; j > 0; j++)
{
if (array[j]< array[j+1])
{
int temp =array[j];
array[j] =array[j+1];
array[j -+1] =temp;
}
}
}
}
2. C#中有哪些常用的容器类,各有什么特点。
List,HashTable,Dictionary,Stack,queue
List:索引泛型容器访问速度快修改速度慢
HashTable/Dictionary:散列表格式查询效率高空间占用较大
Stack:后进先出
Queue: 先进先出
3. C#中常规容器和泛型容器有什么区别,哪种效率高?
不带泛型的容器需要装箱和拆箱操作速度慢所以泛型容器效率更高数据类型更安全
4. 有哪些常见的数值类?
简单值类型--包括整数类型、实数类型、字符类型、布尔类型
复合值类型--包括结构类型、枚举类型
5. C#中委托和接口有什么区别?各用在什么场合?
接口(interface)是约束类应该具备的功能集合,约束了类应该具备的功能,使类从千变万化的具体逻辑中解脱出来,便于类的管理和扩展,同时又合理解决了类的单继承问题。
C#中的委托是约束方法集合的一个类,可以便捷的使用委托对这个方法集合进行操作。
在以下情况中使用接口:
1.无法使用继承的场合
2.完全抽象的场合
3.多人协作的场合
以上等等
在以下情况中使用委托:多用于事件处理中
6. C#中unsafe关键字是用来做什么的?什么场合下使用?
非托管代码才需要这个关键字一般用在带指针操作的场合
7. C#中ref和out关键字有什么区别?
ref修饰参数,表示进行引用传递,out修饰参数也表示进行引用传递,但传递的引用只为带回返回值 ref又进又出 out不进只出
8. For,foreach,Enumerator.MoveNext的使用,与内存消耗情况
for 循环可以通过索引依次进行遍历,foreach和Enumerator.MoveNext通过迭代的方式进行遍历。内存消耗上本质上并没有太大的区别。但是在Unity中的Update中,一般不推荐使用foreach 因为会遗留内存垃圾。
9. 函数中多次使用string的+=处理,会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决。
通过StringBuilder那进行APPend,这样可以减少内存垃圾
1. GameObject a=newGameObject() GameObject b=a 实例化出来了A,将A赋给B,现在将B删除,问A还存在吗?
存在,b删除只是将它在栈中的内存删除,而A对象本身是在堆中,所以A还存在
2. 你拥有A块钱,一瓶水B块钱,每瓶水可以得到一个瓶盖,每C个瓶盖可以换一瓶水请写出函数求解上面题目,上面题目ABC为参数
public static int Buy(int a,int b,int c) {
return a/b + ForCap(c,a/b);
}
public static int ForCap(int c,int d) {
if (d<c) {
return 0;
} else {
return d/c + ForCap(c,d/c + d%c);
}
}
3. 有一排开关,第一个人把所有的开关打开,第二个人按2的倍数的开关,第三个人按3的倍数的开关,以此类推,现在又n个开关,k个人,写函数求最后等两者的开关,输入参数n和k
static void Main(string[] args) {
int n =int.Parse(console.ReadLine());
int k = int.Parse(Console.ReadLine());
Function(100,100);
}
static void Function(int n, int k) {
int i, j = 0;
bool[] a = new bool[1000]; //初始false:关灯,true:开灯
for (i = 1; i <= k; i++) //k个人
for (j = 1; j <= n; j++) //n个灯
if (j % i == 0)
a[j] = !a[j]; //取反,false变true,原来开变关,关变开
for (i = 1; i<= n; i++) //最后输出a[i]的值就可以了
if (a[i]) //灯亮着
Console.WriteLine(i);
}
4. 数制转换,将任意整数转换成8进制形式
static voidMain(string[] args) {
int n;
n =int.Parse(Console.ReadLine());
Console.WriteLine("输入的10进制为:{0}",n);
Console.Write("转换为8进制数为:");
d2o(n);
}
static voidd2o(int n) {
if (n > 7) {
d2o(n / 8);
}
Console.Write(n%8);
}
5. 找出200以内的素数。
static voidMain(string[] args) {
int count = 0;
for (int i = 1;i < 200; i++)
{
//外层循环:要判断的数
for (int j = 2;j <=i; j++)
{
if (i % j == 0&&i!=j)
{
break;
}
if (j == i )
{//结束的条件:最后一个数还没有被整除
count++;
Console.WriteLine(i);
}
}
}
Console.WriteLine(count);
}
6. 打印杨辉三角形
public staticvoid YHSJ(){
int [][]a= newint[7][] ;
a[0] = newint[1]; //a[0][0]=1;
a[1] = newint[2] ;
for (int i = 0;i < 7; i++) {
a[i] = newint[i+1] ;
a[i][0] =1;
a[i][i]=1;
if(i>1){//求出中间的数据
for(intj=1;j<i; j++){
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
}
for (int i=0;i<a.Length; i++){
for (int k = 0;k < a.Length-1-i; k++){
Console.Write("");
}
for(intj=0;j<a[i].Length; j++ ) {
Console.Write(a[i][j]+ "");
}
Console.WriteLine();
}
}
7. )
public staticvoid Compute(){
Console.WriteLine ((DateTime.Now -DateTime.Parse("2000-01-01")).Days%5<3?"打鱼":"晒网");
}
8. 假设当前市场价一只鸡10元,一只鸭12元5角。请写一个函数ShowPrice,输入参数分别为鸡和鸭的个数(非负整型),功能为显示出总价钱,精确到分。例如调用ShowPrice(5,10)后输出175.00。请注意程序的可读性和易于维护性。
static void ShowPrice(int num_chicken, int num_duck) {
float totalPrice= 0.00f;
float price_chicken = 10f;
float price_duck = 12.5f;
totalPrice = num_chicken * price_chicken+ num_duck * price_duck;
Console.WriteLine("总价钱为:{0:0.00}", totalPrice);
}
9. 请写一个函数,用于返回n!(阶乘)结果末尾连续0的个数,如GetZeroCount(5)返回1,因为5! = 120,末尾连续1个0
static void Main(string[] args){
int fac =Factorial(5);
Console.WriteLine(CountZero(fac));
}
public staticint Factorial(int n){
if (n == 1){
return 1;
}else{
return n *jiecheng(n - 1);
}
}
//求连续的0的个数
public static int CountZero(int num){
int result = 0;// 最后的结果
String numStr =num.ToString();
for (int i =numStr.Length - 1; i >= 0; i--){
if (numStr[i] =='0'){
result ++;
}
Else
{
break;
}
}
returnresult;
}
相关阅读
C# 使用FileSystemWatcher类来对一个日志文件的变化进
C# 使用FileSystemWatcher类来对一个日志文件的变化进行实时监测 应用场景描述:在我的工作中,遇到这么一个情况,有一个没有源码的程
转自:我想有个长长的名字的博客,剑指offer 面试题2 Singleton模式 C++实现题目:实现Singleton模式 以下内容是我在看《剑指offer》
1.首先我们需要以下几个dll,第一个和第二个需要在项目中引用,第三个是用来导入ToolBox的,第四个是用来汉化的的,语言是可以选择的。默
C#高级特性:动态绑定 动态绑定 动态绑定将类型绑定(类型解析、成员和操作过程)从编译时推迟到了运行时。在编译时,如果程序员知
金三银四到来了,找工作的好时候到了,小伙伴们是不是都在忙着找工作呢,小弟前一阵也是忙着在找工作,面试了好多公司,所幸的是进到了自己