C# 面试手册

关键字

C# 中用 sealed 修饰的类有什麽特点?

密封,不能继承。

密封类在声明中使用sealed 修饰符,这样就可以防止该类被其它类继承。如果试图将一个密封类作为其它类的基类,C#将提示出错。理所当然,密封类不能同时又是抽象类,因为抽象总是希望被继承的。

new关键字的作用?

  • 运算符:创建对象实例
  • 修饰符:在派生类定义一个重名的方法,隐藏掉基类方法
  • 约束:泛型约束定义,约束可使用的泛型类型,如:
public class ItemFactory<T> where T : IComparable, new()
{
}

const和readonly有什么区别?

都可以标识一个常量。主要有以下区别:

  1. 初始化位置不同。const必须在声明的同时赋值;readonly即可以在声明处赋值,也可以在静态构造方法(必须是静态构造方法,普通构造方法不行)里赋值。
  2. 修饰对象不同。const即可以修饰类的字段,也可以修饰局部变量;readonly只能修饰类的字段
  3. const是编译时常量,在编译时确定该值;readonly是运行时常量,在运行时确定该值。
  4. const默认是静态的;而readonly如果设置成静态需要显示声明
  5. 修饰引用类型时不同,const只能修饰string或值为null的其他引用类型;readonly可以是任何类型。

静态成员和非静态成员的区别

  1. 静态成员用 static 修饰符声明,在类被实例化时创建,通过类进行访问
  2. 不带 static 的变量时非静态变量,在对象被实例化时创建,通过对象进行访问,
  3. 静态方法里不能使用非静态成员,非静态方法可以使用静态成员
  4. 静态成员属于类,而不属于对象

C#中 static 关键字的作用?

  • 对类有意义的字段和方法使用static 关键字修饰,称为静态成员,通过类名加访问操作符“ .”进行访问;
  • 对类的实例有意义的字段和方法不加static 关键字,称为非静态成员或实例成员。

注:静态字段在内存中只有一个拷贝,非静态字段则是在每个实例对象中拥有一个拷贝。而方法无论是否为静态,在内存中只会有一份拷贝,区别只是通过类名来访问还是通过实例名来访问。

C# 成员变量和成员函数前加static 的作用?

它们被称为常成员变量和常成员函数,又称为类成员变量和类成员函数。分别用来反映类的状态。

比如类成员变量可以用来统计类实例的数量,类成员函数负责这种统计的动作。不用new

C# 中索引器的实现过程,是否只能根据数字进行索引,请描述一下

C#通过提供索引器,可以象处理数组一样处理对象。特别是属性,每一个元素都以一个get 或set 方法暴露。索引器不单能索引数字(数组下标),还能索引一些HASHMAP 的字符串,所以,通常来说,C#中类的索引器通常只有一个,就是THIS,但也可以有无数个,只要你的参数列表不同就可以了索引器和返回值无关, 索引器最大的好处是使代码看上去更自然,更符合实际的思考模式。

微软官方一个示例:

索引器允许类或结构的实例就像数组一样进行索引。索引器类似于属性,不同之处在于它们的访问器采用参数。

在下面的示例中,定义了一个泛型类,并为其提供了简单的 get 和 set 访问器方法(作为分配和检索值的方法)。Program 类为存储字符串创建了此类的一个实例。

class SampleCollection<T>
{
    private T[] arr = new T[100];
    public T this[int i]
    {
        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]);
    }
}

详见:https://www.cnblogs.com/promise-7/archive/2012/01/12/2320401.html

ref和out有什么区别

ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。

out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。

相同点:

  1. 都能返回多个返回值。
  2. 若要使用 ref 和out参数,则方法定义和调用方法都必须显式使用 ref和out 关键字。(也就是在定义和调用方法时参数前要有ref和out关键字)在方法中对参数的设置和改变将会直接影响函数调用之处(参数的初始值)。

不同点:

  1. ref指定的参数在函数调用时候必须初始化,不能为空的引用。而out指定的参数在函数调用时候可以不初始化;
  2. out指定的参数在进入函数时会清空自己,必须在函数内部赋初值。而ref指定的参数不需要。

总结

  1. ref和out使用时候一定要在参数前加关键字。
  2. ref是在外部初始化,内部不需要再初始化。
  3. out关键字一定要在内部初始化。(实参外部有没有初始化不影响)。

注意:string 作为特殊的引用类型,其操作是与值类型看齐的,若要将方法内对形参赋值后的结果传递出来,需要加上ref 或out 关键字。

说明C#中的方法声明参数关键字params,ref,out的意义及用法?

  1. params 关键字,官方给出的解释为用于方法参数长度不定的情况。有时候不能确定一个方法的方法参数到底有多少个,可以使用params关键字来解决问题
  2. ref 关键字:使用引用类型参数,在方法中对参数所做的任何更改都将反应在该变量中
  3. out 关键字:out 与ref相似但是out 无需进行初始化。

as和is的区别

as在转换的同时判断兼容性,如果无法进行转换,返回位null(没有产生新的对象),as转换是否成功判断的依据是是否位null is只是做类型兼容性判断,并不执行真正的类型转换,返回true或false,对象为null也会返回false。

as比is效率更高,as只需要做一次类型兼容检查

谈谈 final、finally的区别

  • final : 不能作为父类被继承。一个类不能声明是final , 又声明为abstract。
  • finally:用于trycatchfinally结构,用于异常处理时执行任何清除操作。

简述 C# 成员修饰符

  • abstract:指示该方法或属性没有实现。
  • const:指定域或局部变量的值不能被改动。
  • event:声明一个事件。
  • extern:指示方法在外部实现。
  • override:对由基类继承成员的新实现。
  • readonly:指示一个域只能在声明时以及相同类的内部被赋值。
  • static:指示一个成员属于类型本身,而不是属于特定的对象。
  • virtual:指示一个方法或存取器的实现可以在继承类中被覆盖。