阅读(4495) (25)

c#面试题及答案整理

2018-05-10 14:39:32 更新

下文是W3Cschool为大家整理的一些比较经典的C#面试题,大家不妨来试试,不看答案,你能答对几题呢?


1.简述 private、 protected、 public、internal 修饰符的访问权限

答:

private 私有成员, 在类的内部才可以访问(只能从其声明上下文中进行访问)
protected 保护成员,该类内部和从该类派生的类中可以访问
Friend 友元 ,声明 friend 元素的程序集中的代码可以访问该元素,而不能从程序集外部访问。
Protected Friend 在派生类或同一程序集内都可以访问。
public 公共成员,完全公开,没有访问限制。  
internal 在同一程序集中可以访问。(很少用)

2.列举ASP.NET页面之间传递值的几种方式

答:

  1. 使用QueryString,如....?id=1;response. Redirect()....
  2. 使用Session变量
  3. 使用Server.Transfer
  4. 使用Application
  5. 使用Cache
  6. 使用HttpContext的Item属性
  7. 使用文件
  8. 使用数据库
  9. 使用Cookie

3.一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30位数是多少,用递归算法实现

答:

public class MainClass {
    public static void Main(){
        Console.WriteLine(Foo(30));      
    }
    public static int Foo(int i){
        if (i <= 0) return 0;
        else if(i > 0 && i <= 2) return 1;
        else return Foo(i - 1) + Foo(i - 2);
    }
}

4.C#中的委托是什么?事件是不是一种委托?

答:

委托是将一种方法作为参数代入到另一种方法。

是,事件是一种特殊的委托。  

比如:onclick事件中的参数就是一种方法。


5.实现多态的过程中overload 重载与override 重写的区别

答:

overload 重载是方法的名称相同,参数或参数类型不同,进行多次重载以适应不同的需要。

Override 是进行基类中函数的重写,实现多态。


6.请编程实现一个冒泡排序算法?

答:

int [] array = new int [*];
int temp = 0;
for(int i = 0; i<array.Length-1; i++){
    for(int j = i+1 ; j < array.Length ; j++){
        if (array[j] < array[i]){
            temp = array[i] ;
            array[i] = array[j] ;
            array[j] = temp ;
        }  
    }
}

或者

public static void bubble_sort(int[] x){
    for (int i = 0; i < x.Length; i++){
        for (int j = i; j < x.Length; j++){
            if (x[i] < x[j]){   //从大到小排序
                int temp;
                temp = x[i];
                x[i] = x[j];
                x[j] = temp;
            }
        }
    }
}
static void Main(string[] args){
    int[] huage = { 1, 5, 2, 9, 3, 7, 6,4,8,0};
    bubble_sort(huage);
    foreach (var a in huage){
    Console.WriteLine(a );
    }
}

7.描述一下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; //访问器采用参数
        }
    }
}

// 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"; //这里 使用索引器进行引用
    System.Console.WriteLine(stringCollection[0]);
    }
}

索引器使得对象可按照与数组相似的方法进行索引。

get 访问器返回值。set 访问器分配值。

this 关键字用于定义索引器。

value 关键字用于定义由 set 索引器分配的值。

索引器不必根据整数值进行索引,由您决定如何定义特定的查找机制。

索引器可被重载。

索引器可以有多个形参,例如当访问二维数组时。


8.用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层?

答:

使用MVC模式分层

一般为3层:数据访问层,业务层,表示层。

数据访问层对数据库进行增删查改。

业务层一般分为二层,业务表观层实现与表示层的沟通,业务规则层实现用户密码的安全等。

表示层为了与用户交互例如用户添加表单。


9.什么是装箱和拆箱?

答:

装箱就是隐式的将一个值型转换为引用型对象。

拆箱就是将一个引用型对象转换成任意值型。

比如:

int i=0;
System.Object obj=i;

这个过程就是装箱!就是将 i 装箱!

比如:

int i=0;
System.Object obj=i;
int j=(int)obj;

这个过程前2句是将 i 装箱,后一句是将 obj 拆箱!


10.什么是受管制(托管)的代码?

答:

托管代码是运行.NET 公共语言运行时CLR的代码。

unsafe:非托管代码,不经过CLR运行,程序员自行分配和释放内存空间。


11.ADO.net中常用的对象有哪些?分别描述一下。

答:

DataSet:数据集。

DataCommand:执行语句命令。

DataAdapter:数据的集合,用于填充。

DataReader:数据只读器

Connection:数据库连接对像

Command:数据库命令


12.什么是Code-Behind技术?

答:代码后置。


13.在.net中,配件的意思是?

答:程序集。(中间语言,源数据,资源,装配清单)


14.常用的调用WebService的方法有哪些?

答:

1.使用WSDL.exe命令行工具。

2.使用VS.NET中的Add Web Reference菜单选项


15.在C#中,string str = null 与 string str = “” 请尽量使用文字或图象说明其中的区别。

答:

string str = null ​是不给他分配内存空间,而​string str = ""​ 给它分配长度为空字符串的内存空间。


16.请详述在C#中类(class)与结构(struct)的异同?

答:

class可以被实例化,属于引用类型,class可以实现接口和单继承其他类,还可以作为基类型,是分配在内存的堆上的。

struct属于值类型,不能作为基类型,但是可以实现接口,是分配在内存的栈上的。


17.写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的。

答:

解1:  

select top 10 * from A where id not in (select top 30 id from A)

解2:  

select top 10 * from A where id > (select max(id) from (select top 30 id from A )as A)

18.GC是什么? 为什么要有GC?

答:

GC是垃圾收集器。程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:

System.gc()​或者​Runtime.getRuntime().gc()


19.String s = new String("xyz");创建了几个String Object?

答:

两个对象,一个是“xyz”,一个是指向“xyz”的引用对象s。


20.try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?

答:

会执行,在return后执行。


21.Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

答:

Set里的元素是不能重复的,那么用​iterator()​方法来区分重复与否。​equals()​是判读两个Set是否相等。

equals()​和==方法决定引用值是否指向同一对象​equals()​在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。


22.谈谈final, finally, finalize的区别。

答:

final:修饰符(关键字),如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载

finally:在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。

finalize:方法名。Java 技术允许使用 ​finalize()​ 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 ​finalize()​ 方法以整理系统资源或者执行其他清理工作。​finalize()​方法是在垃圾收集器删除对象之前对这个对象调用的。


23.如何处理几十万条并发数据?

答:

用存储过程或事务。取得最大标识的时候同时更新..注意主键不是自增量方式这种方法并发的时候是不会有重复主键的..取得最大标识要有一个存储过程来获取.


24.进程和线程的区别?

答:

进程是系统进行资源分配和调度的单位;线程是CPU调度和分派的单位,一个进程可以有多个线程,这些线程共享这个进程的资源。


25.堆和栈的区别?

答:

栈:由编译器自动分配、释放。在函数体中定义的变量通常在栈上。

堆:一般由程序员分配释放。用newmalloc等分配内存函数分配得到的就是在堆上。


26.成员变量和成员函数前加static的作用?

答:

它们被称为常成员变量和常成员函数,又称为类成员变量和类成员函数。分别用来反映类的状态。比如类成员变量可以用来统计类实例的数量,类成员函数负责这种统计的动作。


27.请指出GAC的含义?

答:

全局程序集缓存。


28.DataReader与Dataset有什么区别?

DataReaderDataSet最大的区别在于:DataReader使用时始终占用SqlConnection在线操作数据库。

任何对SqlConnection的操作都会引发DataReader的异常。因为DataReader每次只在内存中加载一条数据,所以占用的内存是很小的。

因为DataReader的特殊性和高性能,所以DataReader是只进的,你读了第一条后就不能再去读取第一条了。 

DataSet则是将数据一次性加载在内存中,抛弃数据库连接,读取完毕即放弃数据库连接。

因为DataSet将数据全部加载在内存中,所以比较消耗内存。但是确比DataReader要灵活,可以动态的添加行、列、数据、对数据库进行回传更新操作。


29.在c#中using和new这两个关键字有什么意义,请写出你所知道的意义?using 指令和语句 new 创建实例 new 隐藏基类中方法。

答:

using:引入名称空间或者使用非托管资源,使用完对象后自动执行实现了IDisposable接口的类的Dispose方法

new:新建实例或者隐藏父类方法


30.什么是虚函数?什么是抽象函数?

答:

虚函数:没有实现的,可由子类继承并重写的函数。​Virtual CallSomeOne();

抽象函数:规定其非虚子类必须实现的函数,必须被重写。​public abstract void CallSomeOne(); 


31.C#中 property 与 attribute的区别,他们各有什么用处,这种机制的好处在哪里?

答:

在C#中有两个属性,分别为PropertyAttribute。

Property比较简单,就是我们常用的getset,主要用于为类中的privateprotected变量提供读取和设置的接口。

Attribute用来说明这个事物的各种特征的一种描述。而Attribute就是干这事的。它允许你将信息与你定义的C#类型相关联,作为类型的标注。

这些信息是任意的,就是说,它不是由语言本身决定的,你可以随意建立和关联任何类型的任何信息。你可以作用属性定义设计时信息和运行时信息,甚至是运行时的行为特征。关键在于这些信息不仅可以被用户取出来作为一种类型的标注,它更可以被编译器所识别,作为编译时的一种附属条件参加程序的编译。

定义属性:属性实际上是一个派生自System.Attribute基类的类。System.Attribute类含有几个用于访问和检查自定义属性的方法。尽管你有权将任何类定义为属性,但是按照惯例来说,从System.Attribute派生类是有意义的


32.HashMap和Hashtable的区别

答:

HashMapHashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。


33..NET和C#有什么区别

答:

.NET一般指 .NET FrameWork框架,它是一种平台,一种技术。

C#是一种编程语言,可以基于.NET平台的应用。


34.启动一个线程是用run()还是start()?

答:

启动一个线程是调用​start()​方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。

run()​方法可以产生必须退出的标志来停止一个线程。


35.数组有没有length()这个方法? String有没有length()这个方法? 

答:

数组没有​length()​这个方法,有length的属性。String有length()​这个方法。 


36.值类型和引用类型的区别?写出C#的样例代码

答:

基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。所有的值类型均隐式派生自 System.ValueType。与引用类型不同,从值类型不可能派生出新的类型。但与引用类型相同的是,结构也可以实现接口。与引用类型不同,值类型不可能包含 null值。然而,可空类型功能允许将 null 赋给值类型。每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。

值类型主要由两类组成:结构、枚举,结构分为以下几类:Numeric(数值)类型、int型(整型)、float型(浮点型)、decimal、​bool​(布尔型)、用户定义的结构。引用类型的变量又称为对象,可存储对实际数据的引用。声明引用类型的关键字:classinterfacedelegate、内置引用类型:objectstring


37.C#中的接口和类有什么异同。

答:

异:不能直接实例化接口。接口不包含方法的实现。接口、类和结构可从多个接口继承。但是C# 只支持单继承:类只能从一个基类继承实现。类定义可在不同的源文件之间进行拆分。

同:接口、类和结构可从多个接口继承。接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。接口可以包含事件、索引器、方法和属性。一个类可以实现多个接口。