C#基础面试题
1.简述private、protected、pubic、internal修饰符的访问权限
答:
- private : 私有成员, 在类的内部才可以访问(只能从其声明上下文中进行访问)
- protected : 保护成员,该类内部和从该类派生的类中可以访问
- Friend:友元 ,声明 friend 元素的程序集中的代码可以访问该元素,而不能从程序集外部访问
- Protected Friend:在派生类或同一程序集内都可以访问
- public : 公共成员,完全公开,没有访问限制
- internal: 在同一命名空间内可以访问
2.C#中的委托是什么?事件是不是一种委托?
答:
委托是将一种方法作为参数代入到另一种方法。
是,事件是一种特殊的委托。 //比如:onclick事件中的参数就是一种方法。
3.实现多态的过程中 overload 重载 与override 重写的区别
答:
override 重写与 overload 重载的区别。重载是方法的名称相同。参数或参数类型不同,进行多次重载以适应不同的需要 override 是进行基类中函数的重写。实现多态。
4.描述一下C#中索引器的实现过程,是否只能根据数字进行索引
答:
C#通过提供索引器,可以象处理数组一样处理对象。特别是属性,每一个元素都以一个get或set方法暴露。索引器不单能索引数字(数组下标),还能索引一些HASHMAP的字符串,所以,通常来说,C#中类的索引器通常只有一个,就是THIS,但也可以有无数个,只要你的参数列表不同就可以了索引器和返回值无关, 索引器最大的好处是使代码看上去更自然,更符合实际的思考模式。
微软官方一个示例:
索引器允许类或结构的实例按照与数组相同的方式进行索引。
索引器类似于属性,不同之处在于它们的访问器采用参数。
在下面的示例中,定义了一个泛型类(class SampleCollection<T>
),并为其提供了简单的 get 和 set访问器 方法(作为分配和检索值的方法)。Program 类为存储字符串创建了此类的一个实例。
class SampleCollection<T>
{
private T[] arr = new T[100];
public T this[int i] //注意,定义索引器。this 关键字用于定义索引器。
{
get
{
return arr[i]; //访问器采用参数
}
set
{
arr[i] = value; //访问器采用参数
}
}
}
class Employee
{
public string firstName;
public string middleName;
public string lastName;
public string this[string index]
{
set
{
switch (index)
{
case "a":
firstName = value;
break;
case "b":
middleName = value;
break;
case "c":
lastName = value;
break;
default: throw new ArgumentOutOfRangeException("index");
}
}
get
{
switch (index)
{
case "a": return firstName;
case "b": return middleName;
case "c": return lastName;
default: throw new ArgumentOutOfRangeException("index");
}
}
}
// This class shows how client code uses the indexer
class Program
{
static void Main(string[] args)
{
SampleCollection<string> stringCollection = new SampleCollection<string>();
stringCollection[0] = "Hello, World"; //这里 使用索引器进行引用
Console.WriteLine(stringCollection[0]);
Employee ee = new Employee();
ee.firstName = "胡";
ee.middleName = "大";
ee.lastName = "阳";
ee["a"] = "sa";
Console.WriteLine("我的名字叫: {0}{1}{2}", ee["a"], ee["b"], ee["c"]);
}
}
-
索引器使得对象可按照与数组相似的方法进行索引。
-
get 访问器返回值。set 访问器分配值。
-
this关键字用于定义索引器。
-
value关键字用于定义由 set 索引器分配的值。
-
索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。
-
索引器可被重载。
-
索引器可以有多个形参,例如当访问二维数组时。
5.什么是装箱和拆箱?
答:
装箱就是隐式的将一个值型转换为引用型对象。
拆箱就是将一个引用型对象转换成任意值型。
int i=0;
System.Object obj=i; //这个过程就是装箱!就是将 i 装箱!
int j=(int)obj;//这个过程 obj 拆箱!
6.什么是受管制(托管)的代码?
答:
托管代码是运行.NET 公共语言运行时CLR的代码
unsafe:非托管代码。不经过CLR运行。程序员自行分配和释放内存空间
7.ADO.Net中常用的对象有哪些?分别描述一下答
答:
- DataSet:数据集。
- DataCommand:执行语句命令。
- DataAdapter:数据的集合,用语填充。
- DataReader:数据只读器
- Connection 数据库连接对像
- Command 数据库命令
8.什么是Code-Behind技术?
答:代码后置
在.net中,配件的意思是?
答:程序集。(中间语言,源数据,资源,装配清单)
9.常用的调用WebService的方法有哪些?
答:
1.使用WSDL.exe命令行工具。
2.使用VS.NET中的Add Web Reference菜单选项
10.在C#中,string str1 = null 与 string str2 =""请尽量使用文字或图象说明其中的区别
答:string str1 = null 是不给他分配内存空间,而string str2 = "" 给它分配长度为空字符串的内存空间,因此str1还不是一个实例化的对象,而str2已经实例化
注意null不是对象,""是对象
11.请详述在C#中类(class)与结构(struct)的异同?
答:class可以被实例化,属于引用类型,class可以实现接口和单继承其他类,还可以作为基类型,是分配在内存的堆上的struct属于值类型,不能作为基类型,但是可以实现接口,是分配在内存的栈上的.
12.GC是什么? 为什么要有GC?
答
GC是垃圾收集器。程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
System.gc()
Runtime.getRuntime().gc()
13.String s = new String("xyz");创建了几个String Object?
答
两个对象,一个是“xyx”,一个是指向“xyx”的引用对象s。
14.abstract class和interface有什么区别?
答:
-
abstract class
abstract 声明抽象类抽象方法,一个类中有抽象方法,那么这个类就是抽象类了。所谓的抽象方法,就是不含主体(不提供实现方法),必须由继承者重写。因此,抽象类不可实例化,只能通过继承被子类重写。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public abstract class Bus
{
public abstract void getName(); //抽象方法
public virtual void getTypes() //虚方法
{
Console.WriteLine("bus");
}
public void getID()//一般方法,若在派生类中重写,须使用new关键字
{
Console.WriteLine("沪A 00000");
}
}
public class car : Bus
{
public override void getName() //继承抽象类,重新抽象方法
{
Console.WriteLine("奥迪");
}
public override void getTypes()//继承抽象类,重新虚方法
{
Console.WriteLine("car");
}
}
class Program
{
static void Main(string[] args)
{
car mycar = new car();
mycar.getName();
mycar.getTypes();
mycar.getID();
}
}
}
输出:
奥迪
car
沪A 00000
-
interface
声明接口,只提供一些方法规约,不提供任何实现;不能用public、abstract等修饰,无字段、常量,无构造函数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public interface IBus
{
void getTypes();
}
public interface IPlane
{
void getfunc();
}
public class Car : IBus,IPlane
{
public void getTypes()
{
Console.WriteLine("car");
}
public void getfunc()
{
Console.WriteLine("fly");
}
}
class Program
{
static void Main(string[] args)
{
Car mycar = new Car ();
mycar.getTypes();
mycar.getfunc();
}
}
}
输出结果:
car
fly
-
区别
1.interface中不能有字段,而abstract class可以有;
2.interface中不能有public等修饰符,而abstract class 可以有。
3.interface 可以实现多继承
15..try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
答:会执行,在return前执行。
16.C#中equal与==的区别
答:C#中,判断相等有两种方式,一种是传统的==操作,一种是object提供的Equals方法。二者的区别在于:
一、==操作符判断的是堆栈中的值,Equlas判断的是堆中的值
C#提供值类型和引用类型,值类型存储在栈上,故用==判断是直接判断其值是否相等,因为值类型不存在堆中的数据,因此值类型的Equals也是判断数据。即,对于值类型而言,==与Equals相同,均是判断其值是否相等。
对于引用类型而言,其栈中存储的是对象的地址,那么==就是比较两个地址是否相等,即是否指向同一个对象;Equals函数则是比较两个对象在堆中的数据是否一样,即两个引用类型是否是对同一个对象的引用。
二、String类型特殊
String类型虽然是引用类型,但是对String对象的赋值却按照值类型操作。
例如:
String s1="hello";
String s2="hello";
对s2初始化的时候,并没有重新开辟内存,而是直接将其地址指向s1的内容“hello”。这样一来,string类型虽然是引用类型,但是其==操作和Equals操作都是一样的,均比较值是否相等。
三、与GetHashCode()的关系
若两对象Equals相等,那么其GetHashCode()必定相等;但是反过来,若GetHashCode()相等,那么这两个对象Equals方法比较结果不一定相同。(为了获取最佳性能,hash函数为对象内容生成的数字是随机分布的,这就意味着,内容不同的对象,有可能生成的数字是一样的,但可以认为这种概率非常小)
下面示例说明:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class People
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public People(string name)
{
this.name = name;
}
}
class Program
{
static void Main(string[] args)
{
string a = "hello";
string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
Console.WriteLine(a == b); //True
Console.WriteLine(a.Equals(b));//True
Console.WriteLine("*********");
int m = 3;
int n = 3;
Console.WriteLine(n == m);//True
Console.WriteLine(n.Equals(m));//True
Console.WriteLine("*********");
object g = a;
object h = b;
Console.WriteLine(g == h);//False
Console.WriteLine(g.Equals(h));//True
Console.WriteLine(g.GetHashCode() + " " + h.GetHashCode()); //1025947313 1025947313
Console.WriteLine("*********");
People p1 = new People("Jimmy");
People p2 = new People("Jimmy");
Console.WriteLine(p1 == p2); //False
Console.WriteLine(p1.Equals(p2)); //False
Console.WriteLine(p1.GetHashCode() + " " + p2.GetHashCode());//43495525 55915408
Console.WriteLine("*********");
People p3 = new People("Jimmy");
People p4 = p3;
Console.WriteLine(p3 == p4);//True
Console.WriteLine(p3.Equals(p4));//True
}
}
}
在C#中,string 类型的特点有:
(1)属于基本数据类型;
(2)是引用类型;
(3)只读;
(4) string a="1123"; string b="1123";
那么a和b指向同一个内存地址;
但是并非2个相同值相等的字符串就对应同一个内存地址;
17.进程和线程的区别?
答:进程是系统进行资源分配和调度的单位;线程是CPU调度和分派的单位,一个进程可以有多个线程,这些线程共享这个进程的资源。
18.堆和栈的区别?
答
栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。
堆:一般由程序员分配释放。用new、malloc等分配内存函数分配得到的就是在堆上。
19.请指出GAC的含义?
答:全局程序集缓存。
20:DataReader与Dataset有什么区别?
答:
DataReader和DataSet最大的区别在于,DataReader使用时始终占用SqlConnection,在线操作数据库.任何对SqlConnection的操作都会引发DataReader的异常.因为DataReader每次只在内存中加载一条数据,所以占用的内存是很小的..因为DataReader的特殊性和高性能.所以DataReader是只进的.你读了第一条后就不能再去读取第一条了. DataSet则是将数据一次性加载在内存中.抛弃数据库连接.读取完毕即放弃数据库连接.因为DataSet将数据全部加载在内存中.所以比较消耗内存.但是确比DataReader要灵活.可以动态的添加行,列,数据.对数据库进行回传更新操作
21.在c#中using和new这两个关键字有什么意义,请写出你所知道的意义
答:
using 引入名称空间或者使用非托管资源,使用完对象后自动执行实现了IDisposable接口的类的Dispose方法
new 新建实例或者隐藏父类方法
22.什么是虚函数?什么是抽象函数?
答:
虚函数:没有实现的,可由子类继承并重写的函数。Virtual CallSomeOne();
抽象函数:规定其非虚子类必须实现的函数,必须被重写。public abstract void CallSomeOne();
23.什么是SOAP,有哪些应用。
答:
simple object access protocal,简单对象接受协议.以xml为基本编码结构,建立在已有通信协议上(如http,不过据说ms在搞最底层的架构在tcp/ip上的soap)的一种规范Web Service使用的协议
24.C#中 property 与 attribute的区别,他们各有什么用处,这种机制的好处在哪里?
答:
在C#中有两个属性,分别为Property和Attribute,
- Property比较简单,就是我们常用的get和set,主要用于为类中的private和protected变量提供读取和设置的接口。
- Attribute用来说明这个事物的各种特征的一种描述。而Attribute就是干这事的。它允许你将信息与你定义的C#类型相关联,作为类型的标注。这些信息是任意的,就是说,它不是由语言本身决定的,你可以随意建立和关联任何类型的任何信息。你可以作用属性定义设计时信息和运行时信息,甚至是运行时的行为特征。关键在于这些信息不仅可以被用户取出来作为一种类型的标注,它更可以被编译器所识别,作为编译时的一种附属条件参加程序的编译。定义属性:属性实际上是一个派生自System.Attribute基类的类。System.Attribute类含有几个用于访问和检查自定义属性的方法。尽管你有权将任何类定义为属性,但是按照惯例来说,从System.Attribute派生类是有意义的
25.用sealed修饰的类有什么特点?
答:
密封,不能继承。
26.大概描述一下ASP。NET服务器控件的生命周期
答
初始化 加载视图状态 处理回发数据 加载 发送回发更改通知 处理回发事件 预呈现 保存状态 呈现 处置 卸载
27.&和&&的区别
答
&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and).
27.列举ASP.NET 页面之间传递值的几种方式
答
- 使用QueryString, 如...?id=1; response.Redirect()
- 使用Session变量
- 使用Server.Transfer (目前很少使用)
- 使用Application
- 使用Cache
- 使用HttpContext的Item属性
- 使用文件
- 使用数据库
- 使用Cookie
28. 什么叫做程序域?
答:应用程序域可以理解为一种轻量级进程。起到安全的作用,占用资源小
29. 什么是强命名程序集
答:程序集需要经过加密签名,强命名程序集可以部署到全局程序集缓存中,成为公共程序集
30.ASP.NET的身份验证方式有哪些?分别是什么原理
答:Windows(默认) 用IIS控制
Form(窗体)用账户
Passport(密钥)
31.分析以下代码,完成填空
string strTmp = "abcdefg某某某";
int i= System.Text.Encoding.Default.GetBytes(strTmp).Length;
int j= strTmp.Length;
以上代码执行完后,i= j=
答:i=13,j=10 (汉子占两个字节)
32. 根据线程安全的相关知识,分析以下代码,当调用test方法时,i>10 时是否会引起死锁?
public void test(int i){
lock(this){
if(i>10){
i--;
test(i);
}
}
}
答:不会引起死锁。因为int是按值传递的,所以每次改变的只是一个副本,因此不会出现死锁,但是如果换成object,那么就会发生死锁
33. 简要谈一下您对微软.NET架构下remoting和webservice两项技术的理解以及实际中的应用
答:remoting是利用TCP/IP,二进制传送提高效率。webservice 是利用http,穿透防火墙
34.启动一个线程用run()还是start()?
答:启动一个线程用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行,并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。