这一周章老师讲了C#有关类的方面的知识,由于与C++,JAVA等语言类似之处不少,所以学起来不是特别吃力。但C#中类也有着不少新颖而有趣的用法与规则,本次学习记录就主要以探究这些内容为主。
1.从C#4.0开始支持optional arguments
optional arguments,即可选参数。(翻译如有错误,请指正!)
用下列代码可快速简简洁说明什么是optional arguments:
1 class myClass 2 { 3 public void TestParam(int aaa, float bbb = 5.5f) 4 { 5 … 6 } 7 } 8 … 9 myClass myCs= new myClass();10 myCs. TestParam(aaa);11 myCs. TestParam(aaa, 6.8);
这是可以编译通过的。也就是说,传入函数的参数是可变的,有一些预先定义好的参数可定义不用传进去,函数将自动采用它们的默认值。
下面通过一个简单的实例看一下效果:
1 namespace Class3Test 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Email email = new Email(); 8 //试验可变函数 9 email.SendMail("bob@foo.com", "Hello World");10 email.SendMail("bob@foo.com", "Hello World", isBodyHtml: true);//告诉编译器跳到了哪一个参数11 email.SendMail("bob@foo.com", "Hello World", true, true);12 13 Console.ReadKey();14 }15 16 class Email17 {18 public void SendMail(string toAddress, string bodyText, 19 bool ccAdministrator = true, bool isBodyHtml = false)20 {21 Console.WriteLine("{0}, {1}, {2}, {3}", toAddress, bodyText, ccAdministrator, isBodyHtml);22 }23 }24 25 }26 }
运行结果如下:
代码浅显易懂,这里就不在解释。不过需要牢记于心的是中间跳过可选参数的时候要使用 参数名:值 这样的形式告诉编译器该语句跳到了哪一个参数,毕竟编译器没有这么智能。
2.ref/out参数
ref参数就类似于C++里的&,可使“方法”返回多个返回值,在函数中对传入的参数值的操作是被保存的。如下列代码:
1 public void TryRef( ref int h, ref int m, ref int s ) 2 { 3 h = 12; 4 m = 34; 5 s = 56; 6 } 7 ... 8 int h1 = 0, m1 = 0, s1 = 0; 9 ...TryRef(ref h1, ref m1, ref s1);10 Console.WriteLine("{0}, {1}, {2}", h1, m1, s1);11 ...
运行结果如图:
但需要注意的一点是定义处“形参”和调用处“实参”都要用 ref 来修饰,缺少一处都无法通过编译。
out参数的用法与ref相似,将上面程序中的ref换成out运行结果是一样的。不过有一点不同的是使用out时,传入的参数是可以只声明而不初始化赋值的。如下列代码所示:
1 public void TryOut( int h, ref int m, out int s ) 2 { 3 h = 12; 4 m = 34; 5 s = 56; 6 } 7 int h1 = 0, m1 = 0, s1;//s1未赋初值 8 ...TryOut( h1, ref m1, out s1); 9 Console.WriteLine("{0}, {1}, {2}", h1, m1, s1);10 ...
运行结果如下:
需要注意的是类似于ref定义处“形参”和调用处“实参”都要用 out来修饰。
3.Sealed修饰符
当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承。 如在下面的代码:
1 class A {} 2 sealed class B : A {}
类 B 从类 A 继承,但是任何类都不能从类 B 继承。
另外还可以在重写基类中的虚方法或虚属性的方法或属性上使用 sealed 修饰符。 这能够允许类从该基类继承,并防止它们重写特定的虚方法或虚属性。如下列代码:
1 class X 2 { 3 protected virtual void F() { Console.WriteLine("X.F"); } 4 protected virtual void F2() { Console.WriteLine("X.F2"); } 5 } 6 class Y : X 7 { 8 sealed protected override void F() { Console.WriteLine("Y.F"); } 9 protected override void F2() { Console.WriteLine("Y.F2"); }10 }11 class Z : Y12 {13 // 错误!尝试编译会遇到错误CS0239.14 protected override void F() { Console.WriteLine("C.F"); }15 16 // 重写F2是允许的17 protected override void F2() { Console.WriteLine("Z.F2"); }18 }
在上面的示例中,Z 从 Y 继承,但 Z 无法重写在 X 中声明并在 Y 中密封的虚函数 F。
4.override 修饰符
要扩展或修改继承的方法、属性、索引器或事件的抽象实现或虚实现,必须使用 override 修饰符。如下列代码:
1 abstract class ShapesClass 2 { 3 abstract public int Area(); 4 } 5 class Square : ShapesClass 6 { 7 int side = 0; 8 9 public Square(int n)10 {11 side = n;12 }13 // 此处必须重写Area函数,否则通不过编译14 public override int Area()15 {16 return side * side;17 }18 19 static void Main() 20 {21 Square sq = new Square(12);22 Console.WriteLine("Area of the square = {0}", sq.Area());23 }24 25 }
在此示例中,Square 类必须提供 Area 的重写实现,因为 Area 继承自抽象的 ShapesClass。
override 方法提供从基类继承的成员的新实现。 由 override 声明重写的方法称为重写基方法。 重写的基方法必须与 override 方法具有相同的签名。
本次学习记录到此为止。有机会以后也会补充一些内容。
望各位老师前辈大牛不吝赐教!