- 传入某个属性的set方法的隐含参数的名称是什么?
value,它的类型和属性所声名的类型相同。 - 如何在C#中实现继承?
在类名后加上一个冒号,再加上基类的名称。 - C#支持多重继承么?
不支持。可以用接口来实现。 - 被protected修饰的属性/方法在何处可以访问?
在继承或间接继承与这个类的子类中可以访问。 - 私有成员会被继承么?
会,但是不能被访问。所以看上去他们似乎是不能被继承的,但实际上确实被继承了。 - 请描述一下修饰符protected internal。
被protected internal修饰的属性/方法只能在它的在同一个程序集(Assembly)中的子类被访问。 - C#提供一个默认的无参数构造函数,当我实现了另外一个有一个参数的构造函数时候,还想保留这个无参数的构造函数。这样我应该写几个构造函数?
两个,一旦你实现了一个构造函数,C#就不会再提供默认的构造函数了,所以需要手动实现那个无参数构造函数。 - C#中所有对象共同的基类是什么?
System.Object. - 重载和覆写有什么区别?
重载提供了对一个方法签名的不同参数调用的实现。覆写提供了子类中改变父类方法行为的实现。 - 在方法定义中,virtual有什么含意?
被virtual修饰的方法可以被子类覆写。 - 能够将非静态的方法覆写成静态方法么?
不能,覆写方法的签名必须与被覆写方法的签名保持一致,除了将virtual改为override。 - 可以覆写私有的虚方法么?
不可以,如果一个方法是虚方法,就不应该定义成私有的! - 能够阻止某一个类被其他类继承么?
可以,使用关键字sealed。 - 能够实现允许某个类被继承,但不允许其中的某个方法被覆写么?
可以,标记这个类为public,并标记这个方法为sealed。(注意:这个方法必须是覆盖了父类中的一个虚方法,否则,无法使用sealed) - 什么是抽象类(abstract class)?
一种不可以被实例化的类。抽象类中一般含有抽象方法,当然也可有具体实现。继承类只有实现过所有抽象类的抽象方法后才能被实例化。 - 何时必须声明一个类为抽象类?
当这个类中包含抽象方法时,或是该类并没有完全实现父类的抽象方法时。 - 接口(interface)是什么?
只含有共有抽象方法(public abstract method)的类。这些方法必须在子类中被实现。 - 为什么不能指定接口中方法的修饰符?
接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。他们默认为公有方法。 - 可以继承多个接口么?
当然。 - 那么如果这些接口中有重复的方法名称呢?
这种情况中你可以决定如何实现。当然需要特别得小心。但是在编译环节是没有问题的。 - 接口和抽象类的区别是什么?
接口中所有方法必须是抽象的,并且不能指定方法的访问修饰符。抽象类中可以有方法的实现,也可以指定方法的访问修饰符。 - 如何区别重载方法?
不同的参数类型,不同的参数个数,不同的参数顺序。 - const和readonly有什么区别?
const关键字用来声明编译时常量,readonly用来声明运行时常量。 - System.String 和System.StringBuilder有什么区别?
System.String是不可变的字符串。System.StringBuilder存放了一个可变的字符串,并提供一些对这个字符串修改的方法。
高级题:
-
- Thread和Process之间有什么区别?.NET新引入了Application Domain的概念,这样他们三个之间有什么区别?引入了Application Domain会带来一些潜在的问题么?
进程可以理解为一个容器,提供进程空间,线程所使用的内存都在进程空间中分配。每个线程有自己的堆栈。APPDomain相当于一个逻辑概念,相当于在进程中逻辑的划分了一些区域,所以线程是可以跨域访问另外的线程。
- Windows Service与普通的EXE在执行过程中有什么区别?
一般前者无界面,有windows的Service服务器负责维护启动和关闭。Exe由用户维护且一般有界面。
- 一个进程可以访问的Windows地址空间有多大?等于系统的虚拟内存大小么?这两方面将对系统的设计产生什么样的影响?
a.跟数据总线有关系。一般32位操作系统,寻址空间可以达到4GB,所以一个进程可以访问的地址也为4GB(不过实际上,有2GB是留给操作系统使用的,4M是不可访问的,剩下的空间才供进程使用)。
b.不等于虚拟内存。
c.寻址空间和数据总线的宽度有关系。虚拟内存会消耗CPU处理时间。因为需要做内外存的转换工作。
- EXE和DLL之间的区别是什么?在系统设计中应该如何选择使用它们?
a..Exe有自己的进程空间,dll没有,dll只能被引用后,和exe共享进程空间才能被调用和运行(其实还有rundll32命令可以启动dll,该系统命令本质上就是为其提供进程空间)。
b.dll也叫动态链接库,可以将反复使用的共有代码和资源放在动态链接库中,这样在内存中只会有一个副本,节约内存空间(不同的进程根据不同的重定位信息可以定位到制定的dll中)。
- 普通的EXE与.NET EXE的执行过程有什么不同?
普通exe可以直接在操作系统上执行,但是.net exe需要jit的及时编译,并在托管环境下(即CLR的控制下)运行
- 什么是弱类型,什么是强类型?在系统设计中应该首先考虑使用哪种类型?
弱类型在一定程度上允许不同类型的数据进行相互操作和运算,但是强类型不允许,因为强类型会做类型检查工作。
- PDB文件是作什么用的?里面包含了什么信息?
程序数据库 (PDB) 文件保存着调试和项目状态信息,使用这些信息可以对程序的调试配置进行增量链接。
- Cyclomatic Complexity是什么?为什么它很重要?
圈复杂度,用于衡量程序的分支数量。一个正常的方法,分值应该控制在5,6个,如果分支数太大,则最好进行方法的分解,避免badsmell.
- 为创建一个critical section以访问某个变量书写一个标准的lock() 并加上double check。
If(m_Instance!=null)
{
lock(this)
{
if(m_Instance!=null))
{
//do something
}
}
}
- 为某个对象实现标准的Dispose模式。
Class MyObject:Idisposable
{
public void Dispose()
{
//do something
}
}
就是实现Idisposable接口,进而实现自定的析构
- 什么是FullTrust? 存在于GAC中的 assembly 拥有FullTrust么?
- 下面这个命令是做什么的?gacutil /l | find /i “system”
全局程序集缓存工具使您可以查看和操作全局程序集缓存和下载缓存的内容。
- 下面这个命令是作什么的? sn -t something.dll
Sn.exe 提供用于密钥管理、签名生成和签名验证的选项。
- 跨防火墙的 DCOM必须打开哪个端口?端口135是用来做什么的?
- 有什么办法可以与现有unmanaged code集成?在集成的时候应该考虑什么问题?
- 简要解释一下OOP与SOA都是用来作什么的?
OOP是一种程序编程架构,包含几个特征:组件,封装,继承,抽象,多态。
SOA叫面向服务架构。
- XmlSerializer是如何工作的?进程运行XmlSerializer时候需要什么样的ACL权限?
ACL访问控制列表。
- 在系统设计时,何时应该使用try catch?何时需要避免使用?
- Debug.Write()和Trace.Write()之间有什么区别?二者分别应该用于何处?
都是断言。Debug.Write()为调试版本,在发行版本里面不会被执行,而Trace.Write在发行版本中会被执行。
- Debug Build和Release Build有什么区别?在执行效率上有什么明显的区别么?
Debug build的版本包含了一些调试信息,执行效率会低一些。
- JIT是针对Assembly还是Method发生的?解释一下为什么.NET的设计者要这样做?
- 简要描述一下GC的执行过程。
当内存减少到某个程度之后,CLR启动垃圾回收,将那些不被引用的对象回收并释放所占用的内存。
- 应该如何选择使用abstract class还是interface?
抽象类可以有实现,接口无实现。接口可以多继承,抽象类不行。
- 在设计一个自定义类型时应如何选择使用Value Type还是Reference Type?
其实要描述的就是引用类型和值类型的区别。可以从内存分布和访问效率两方面谈。
- 对于Value Type和Reference Type,a.Equals(b)的默认实现方式有什么不同?
值类型默认就是指是否相等。引用类型就是比较两个引用是否指向同一个对象。
- .NET中为什么不提供默认的deep copy?如果需要,要如何实现deep copy?
因为深度拷贝涉及到拷贝的级数问题,就是需要深度拷贝到什么层次。在C#中,不可以直接覆写MemberwiseClone方法,可以实现Iclone接口来实现自定义的深度拷贝。
- 相对于.NET 1.1,.NET2.0为了避免过度的boxing/unboxing造成的系统开销提供了哪些支持?
范型。
- String是Value Type还是Reference Type?为什么.NET中的String对象被设置成immutable?
是引用类型。因为字符串对象在操作系统中出现的频率很高,如果为每一个string都分配一个独立的内存,将会是很大的系统开销。所以string 设置为不可变的,就是一种内存驻留技术,本质上就是让同样的字符串都访问同一块内存。比如:s1=”a”,s2=”b”,则s1和s2其实都是指向同一块为”a”的内存;如果现在修改s1=”b”,则s1将不再指向”a”,而是开辟另一块为”b”的内存空间,使s1指向b(其实如果有另一个s3=”b”,则s1就会和s3指向同一个”b”,此时s1不再重新开辟空间)。