错误虚方法必须被明确地覆盖
在C#语言中编程人员在覆盖一个虚方法时必须显性地使用override关健字假设一个Window类是由A公司编写的ListBox和RadioButton类是由B公司的和编程人员在购买的A公司编写的Window类的基础上编写的B公司的编程人员对包括Window类未来的变化情况在内的设计知之甚少
如果B公司的一位编程人员要在ListBox上添加一个Sort方法
public class ListBox : Window
{
public virtual void Sort() {}
}
在A公司发布新版的Window类之前这不会有任何问题如果A公司的编程人员也在Window类中添加了一个Sort方法
public class Window
{
//
public virtual void Sort() {}
}
在C++中Windows类中的Sort方法将成为ListBox类中Sort方法的基础方法在希望调用Windows类中的Sort方法时ListBox类中的Sort方法就会被调用在C#中虚拟函数总是被认为是虚拟调度的根也就是说一旦C#发现一个虚拟的方法就不会再在虚拟链中查找其他虚拟方法如果ListBox再次被编译编译器就会生成一个警告信息
\classcs(): warning CS: ListBoxSort() hides
inherited member WindowSort()
要使当前的成员覆盖原来的方法就需要添加override关健字或者添加new关健字
要消除警告信息编程人员必须搞清楚他想干什么可以在ListBox类中的Sort方法前添加new表明它不应该覆盖Window中的虚方法
public class ListBox : Window
{
public new virtual void Sort() {}
这样就可以清除警告信息如果编程人员确实希望覆盖掉Window中的方法就必须使用override关健字来显性地表明其意图
错误类成员变量的初始化
C#中的初始化与C++中不同假设有一个带有private性质的成员变量age的Person类Employee是由继承Person类而生成的它有一个private性质的salaryLevel成员变量在C++中我们可以在Employee的构造器的初始化部分初始化salaryLevel如下面的代码所示
Employee::Employee(int theAge int theSalaryLevel):
Person(theAge) // 初始化基础类
salaryLevel(theSalaryLevel) // 初始化成员变量
{
// 构造器的代码
}
这种方法在C#中是非法的尽管仍然可以初始化基础类但象上面的代码那样对成员变量初始化就会引起编译错误在C#中我们可以在定义成员变量时的同时对它进行初始化
Class Employee : public Person
{
// 成员变量的定义
private salaryLevel = ; // 初始化
}
注意必须明确地定义每个变量的访问权限
错误布尔型变量与整型变量是两回事儿
if( someFuncWhichReturnsAValue() )
在C#中布尔型变量与整型变量并不相同因此下面的代码是不正确的
if( someFuncWhichReturnsAValue() )
if someFuncWhichReturnsAValue返回零表示false否则表示true的想法已经行不通了这样的好处是原来存在的将赋值运算与相等相混淆的错误就不会再犯了因此下面的代码
if ( x = )
在编译时就会出错因为x=只是把赋给了X而不是一个布尔值
错误switch语句中会有些语句执行不到
在C#中如果一个switch语句执行了一些操作则程序就可能不能执行到下一个语句因此尽管下面的代码在C++中是合法的但在C#中却不合法
switch (i)
{
case :
CallFuncOne();
case : // 错误不会执行到这里
CallSomeFunc();
}
要实现上面代码的目的需要使用一个goto语句
switch (i)
{
case :
CallFuncOne();
goto case ;
case :
CallSomeFunc();
}
如果case语句不执行任何代码则所有的语句都会被执行如下面的代码
switch (i)
{
case : // 能执行到
case : // 能执行到
case :
CallSomeFunc();
}
错误C#中的变量要求明确地赋值
在C#中所有的变量在使用前都必须被赋值因此可以在定义变量时不对它进行初始化如果在把它传递给一个方法前必须被赋值
如果只是通过索引向方法传递一个变量并且该变量是方法的输出变量这是就会带来问题例如假设有一个方法它返回当前时间的小时分秒如果象下面这样编写代码
int theHour;
int theMinute;
int theSecond;
timeObjectGetTime( ref theHour ref theMinute ref theSecond)
如果在使用theHourtheMinute和theSecond这三个变量之前没有对它们进行初始化就会产生一个编译错误
Use of unassigned local variable theHour
Use of unassigned local variable theMinute
Use of unassigned local variable theSecond
我们可以通过将这些变量初始化为或其他对方法的返回值没有影响的值以解决编译器的这个小问题
int theHour = ;
int theMinute = ;
int theSecond = ;
timeObjectGetTime( ref theHour ref theMinute ref theSecond)
这样就有些太麻烦了这些变量传递给GetTime方法然后被改变而已为了解决这一问题C#专门针对这一情况提供了out参数修饰符它可以使一个参数无需初始化就可以被引用例如GetTime中的参数对它本身没有一点意义它们只是为了表达该方法的输出在方法中返回之前Out参数中必须被指定一个值下面是经过修改后的GetTime方法
public void GetTime(out int h out int m out int s)
{
h = Hour;
m = Minute;
s = Second;
}
下面是新的GetTime方法的调用方法
timeObjectGetTime( out theHour out theMinute out theSecond);