1. 默认情况下想使用一些.NET Framework SDK中的命令需要”Visual Studio 200x 命令提示”这个工具。如果想使传统”命令提示符”也支持这些命令应该怎样做呢。当然是配置环境变量。在X:\Program Files\Microsoft Visual Studio 8\VC文件夹下有一个名为vcvarsall.bat的脚本文件,运行它即可完成这个环境变量的配置。
2. checked与unchecked关键字只对整型有效,对于浮点型无效,因为浮点型始终不会出现溢出。checked对于整型溢出会引起OverflowException异常(unchecked中始终不会触发OverflowException异常)。.NET中用Int32.MaxValue表示最大值,Int32.MinValue表示最小值。在checked中MaxValue加1,MinValue减1都会引起异常。
3. 结构和类的主要区别
区别 |
结构 |
类 |
是值类型还是引用类型? |
值类型 |
引用类型 |
实例存储于栈上还是堆上? |
结构实例称为值,存储于栈上 |
实例称为对象,存在于堆上 |
可否声明默认构造函数? |
不可以 |
可以 |
声明自定义的构造函数,还会声明默认构造函数吗? |
会 |
不会 |
如果在自己的构造函数中不初始化一个字段,编译器会帮助初始吗? |
不会 |
会 |
可以在声明一个实例字段的同时初始化吗? |
不可以 |
可以 |
是否可以继承? |
不可以 |
可以由基类继承 |
是否可以存在析构函数? |
不可以 |
可以 |
4. 关于params参数的问题
1) 只能在一维数组上使用params关键字,所以下面的例子无法通过编译:
Public static int Min(params int[,] table)
2) 不能重载一个只基于params关键字的方法。params关键字不构成方法的签名的一部分。如下面两个方法同时存在将无法通过编译:
public static int Min(int[] paramList)
public static int Min(params int[] paramList)
3) 不允许ref或out params数组,如下面两种声明都无法通过编译
public static int Min(ref params int[] paramList)
public static int Min(out params int[] paramList)
4) params数组参数必须是方法的最后一个参数(即,每个方法的参数只能有一个params数组),如下实例将不能通过编译:
public static int Min(params int[] paramList , int i)
编译器会检查并拒绝任何可能有歧义的重载。例如,以下两个Min方法存在歧义;如果传递两个int参数,将无法辨别具体调用哪一个:
public static int Min(params int[] paramList)
public static int Min(int, params int[] paramList)
5) 非params方法总是优先于一个params方法。也就是说,如果愿意,仍然可以为普通情况创建一个方法的重载版本,如下例:
public static int Min(int leftHandSite, int rightHandSide)
public static int Min(params int[] paramList)
对于Min(2,3);这种形式的调用,前者函数将优先使用。
6) 对于params object[]这类特殊参数,其会匹配同方法名任意参数的调用。也可以不向其传递参数,或传递null。这会被作为new object[0]传入。
7) 调用public int Process(params int[] paramList)这样含有参数为参数数组的方法,我们可以传入几个单独的int值,也可以传入一个int数组,如下两种调用方式都是有效的:
Process(2,3,8);
Process(new []{2,3,8});
5. sealed关键字不仅可以修饰class,也可以修饰method,这称为密封方法。一个密封类不能被派生,而一个派生类中不能覆盖密封方法。
6. C#中的default关键字
default关键字常与泛型的类型参数一起使用,由于泛型类型只有在运行时才能确定类型,所有我们不能在编译之前确定初始化一个泛型类型的方法,如一个引用类型我们需要初始化为null,一个值类型我们需要初始化为0,这时使用default关键字就可以实现这个在运行时根据实际类型来初始化的功能。
7. 判断string为空或长度为0时,不要再使用string str = string.Empty;if(str==null||str.length==0),直接使用.net2.0开始提供的新的静态方法:String.IsNullOrEmpty(str)。
8. switch语句的特殊用法
switch语句中的case(分支)数不受限制。我们可以将switch放在一个for循环内,见下面的示例代码:
1 for (int i = 0; i < 5; i++) 2 { 3 switch (i) 4 { 5 case 1: 6 Console.WriteLine("first"); 7 break; 8 case 2: 9 Console.WriteLine("second"); 10 break; 11 //... 12 default: 13 Console.WriteLine("default"); 14 break; 15 } 16 }
9. Conditional特性
Conditional特性允许包含或排除对一个方法的调用,Conditional特性的使用很简单:
[Conditional(“CompileSymbol”)]
特性的构造函数接收一个字符串。如果定义了一个这样的编译符号,编译器会包含所有调用这个方法的代码,这与普通情况一致。如果没有定义这样的编译符号,编译器会忽略代码中所有对这个方法的调用。定义编译符号需要使用条件编译#define来完成。
10. 自定义Attribute的一个小技巧(来自C#图解教程)
虽然在.NET4.0起才开始支持命名参数,但.NET2.0后在应用一个Attribute时,就可以使用类似命名参数的特性来为Attribute传入参数,如下面这个自定义Attribute:
1 public sealed class MyAttributeAttribute :Attribute 2 { 3 public string Description { get; set; } 4 public string Ver { get; set; } 5 public string Reviewer { get; set; } 6 7 public MyAttributeAttribute(string desc) 8 { 9 Description = desc; 10 } 11 }
应用这个Attribute时,我们可以以如下方式给构造函数传入参数:
1 [MyAttribute("An excellent class", Reviewer = "lsxqw", Ver = "7.15.33")]
访问自定义特性
Type类提供了两个方法,用于访问自定义的Attribute:
IsDefined:该方法可以检测某个特性是否应用到某个类上,对于我们上面的示例,我们可以使用下面的方法进行判断:
1 Type t = typeof (MyClass); 2 t.IsDefined(typeof (MyAttributeAttribute), false);
GetCustomAttribute:该方法返回应用到目标类型的特性的数组,该方法返回值为object[]对象,布尔参数指定是否搜索继承树来查找特性。
1 static void CallWhenDone(IAsyncResult iar) 2 { 3 MyDel del = (MyDel)iar.AsyncState; 4 long result = del.EndInvoke(iar); 5 6 Type t = typeof(MyClass); 7 var attrLst = t.GetCustomAttributes(false); 8 //由于我们的例子只应用了一个特性,我们直接取数组第一项 9 MyAttributeAttribute attribute = attrLst[0] as MyAttributeAttribute; 10 if (null != attribute) 11 { 12 Console.WriteLine("{0},{1},{2}", attribute.Description, attribute.Ver, attribute.Reviewer); 13 } 14 }