接口
public class Program { static void Main(string[] args) { IFlyable sp = new SupperMan(); sp.Fly(); sp.Jump(); Console.ReadKey(); } } //定义一个接口 //定义接口使用interface 关键字 //一般接口名要以大写I开头 //接口中只能包含方法【属性、事件、索引器最终都是方法,所以可以说接口中只能包含方法】 //接口中的成员不能有任何访问修饰符,默认是public,如果手动写了访问修饰符这报错!!!! //接口中的成员不能有任何实现,就像抽象方法一样不能有实现 public interface IFlyable { void Fly(); void Jump(); } //使用抽象类与虚方法已经完全可以实现多态了,为什么还要用接口来实现多态? //什么情况下需要使用接口来实现多态? //1>当多个类型不能抽象出合理的父类的时候,但是又要对某些方法进行多态,此时可以考虑使用接口来实现多态。即吧公共的方法抽象到一个接口中,然后让不同的子类实现该接口 //2>因为接口可以多实现,所以解决了类的单继承问题,当一个类需要同时“继承”多个类的行为时,可以考虑使用接口来进行多实现。 //定义一个类来实现该接口 //实现接口的类,必须将接口中的所有成员都实现 //实现接口的类直接实现接口中的方法即可,无需使用override 关键字。 public class SupperMan : IFlyable { public void Fly() { Console.WriteLine("超人在飞....."); } public void Jump() { Console.WriteLine("超人在跳。。。。"); } } public class SpiderMan : IFlyable, IFormattable, IDisposable, ICloneable { public void Fly() { Console.WriteLine("蜘蛛侠在飞。。。"); } public void Jump() { Console.WriteLine("蜘蛛侠在跳。。。"); } #region IFormattable 成员 public string ToString(string format, IFormatProvider formatProvider) { throw new NotImplementedException(); } #endregion #region IDisposable 成员 public void Dispose() { throw new NotImplementedException(); } #endregion #region ICloneable 成员 public object Clone() { throw new NotImplementedException(); } #endregion }
接口练习
案例(继承一个类,同时实现了其他接口)
鸟 麻雀 sparrow 鸵鸟ostrich 企鹅penguin 鹦鹉parrot
鸟能飞,鸵鸟,企鹅不能。。。你怎么办?
鸟类:
public class Bird { public void Eat() { Console.WriteLine("鸟在吃东西。。。。。。"); } }
飞的接口:
public interface IFlyable { void Fly(); }
麻雀类:
public class Penguin : Bird { } /// <summary> /// 麻雀类 /// </summary> class Sparrow : Bird, IFlyable { #region IFlyable 成员 public void Fly() { Console.WriteLine("麻雀飞上青天!"); } #endregion }
鹦鹉类:
public class Parrot : Bird, IFlyable { #region IFlyable 成员 public void Fly() { Console.WriteLine("鹦鹉飞。。"); } #endregion }
鸵鸟类:
public class Ostrich : Bird { }
企鹅类:
public class Penguin : Bird { }
主程序:
public class Program { static void Main(string[] args) { IFlyable fly = new Parrot(); fly.Fly(); Console.ReadKey(); } }
接口练习
public interface ITest { void M1(); int M2(); string M3(string msg); //private string _name; //public string Name //{ // get // { // return _name; // } // set // { // _name = value; // } //} //看起来就是一个“自动属性”,但是该属性出现在了接口中 //所以编译器不会把该属性自动实现,所以必须交给实现该接口的类来实现该属性。 string Name; string this[int index] { get; set; } } public class TestClass : ITest { public void M1() { throw new NotImplementedException(); } public int M2() { throw new NotImplementedException(); } public string M3(string msg) { throw new NotImplementedException(); } public string this[int index] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } } //当一个抽象类实现某个接口的时候,如果实现的时候把接口中的成员标记为了abstract ,同时该类也是一个抽象类,此时可以不对接口中的成员进行实现 public abstract class TestAbstractClass : ITest { public abstract void M1(); public abstract int M2(); public abstract string M3(string msg); public abstract string this[int index] { get; set; } }
接口练习
public class Person { public string Name { get; set; } public int Age { get; set; } } public class Student : Person, ICollectHomework { #region ICollectHomework 成员 public void Collect() { Console.WriteLine("班长收作业!!"); } #endregion } public class BestStudent : Student { } public class Teacher : Person, ICollectHomework { #region ICollectHomework 成员 public void Collect() { Console.WriteLine("老师收作业! "); } #endregion } public interface ICollectHomework { void Collect(); }
练习:
class Program { static void Main(string[] args) { //House house = new House(); //DengJi(house); //DengJi(new Chinese()); //IBarkable bark = new RubberDuck(); //new RealDuck(); //bark.Bark(); Console.ReadKey(); } static void DengJi(IIntroduce djObj) { djObj.Introduce(); } //static void DengJi(Person person) //{ // person.Introduce(); //} //static void DengJi(Chinese cn) //{ //} //static void DengJi(American us) //{ //} //static void DengJi(British uk) //{ //} } class House : IIntroduce { #region IIntroduce 成员 public void Introduce() { Console.WriteLine("房子的详细信息"); } #endregion } //// Person类实现了IIntroduce接口,并且把接口中的Introduce()方法实现成虚方法,所以继承Person类的子类就可以重写该方法了。 //class Person : IIntroduce //{ // public virtual void Introduce() // { // } //} // class Person : IIntroduce { public virtual void Introduce() { } } class Chinese : Person, IIntroduce { public override void Introduce() { Console.WriteLine("我的户口,身份证号码"); } } class American : Person, IIntroduce { public override void Introduce() { Console.WriteLine("社会保险号:00000"); } } class British : Person, IIntroduce { public override void Introduce() { Console.WriteLine(".......;"); } } public interface IIntroduce { /// <summary> /// 介绍说明自己的情况 /// </summary> void Introduce(); }
显示实现接口
class Program { static void Main(string[] args) { //IFace1 face1 = new Person(); //face1.Fly(); //IFace2 face2 = new Person(); //face2.Fly(); //Console.ReadKey(); //======================== Person p = new Person(); p.Fly();//face1中的Fly() IFace1 f1 = new Person(); f1.Fly();//face1中的Fly() IFace2 f2 = new Person(); f2.Fly();//face2中的Fly() Console.ReadKey(); } } public class Person : IFace1, IFace2 { #region MyRegion //public void Fly() //{ // throw new NotImplementedException(); //} ////实现接口的时候在方法名前面加 接口名.方法名() 就叫做显示实现接口。 //void IFace1.Fly() //{ // throw new NotImplementedException(); //} #endregion #region IFace1 成员 public void Fly() { Console.WriteLine("实现了IFace1中的Fly方法。"); } #endregion #region IFace2 成员 //显示实现接口的访问修饰符默认是没有的,类中成员没有写访问修饰符这默认就是private //显示实现接口是私有的所以必须通过接口名才能访问的到。 void IFace2.Fly() { Console.WriteLine("实现了IFace2中的Fly方法。"); } #endregion } public interface IFace1 { void Fly(); } public interface IFace2 { void Fly(); }
接口多继承
public interface IFace1 { void M1(); } public interface IFace2 { void M2(); } public interface IFace3 { void M3(); } public interface IFace4 { void M4(); void M4(string msg); void M4(int n); } public interface IFace5 : IFace1, IFace2, IFace3, IFace4 { } //class MyClass : IFace5 //{ // #region IFace1 成员 // public void M1() // { // throw new NotImplementedException(); // } // #endregion // #region IFace2 成员 // public void M2() // { // throw new NotImplementedException(); // } // #endregion // #region IFace3 成员 // public void M3() // { // throw new NotImplementedException(); // } // #endregion // #region IFace4 成员 // public void M4() // { // throw new NotImplementedException(); // } // #endregion //}
面向对象的五大原则: 单一职责 开放封闭 里氏替换 接口隔离 依赖倒置
类型转换:
class Program { static void Main(string[] args) { #region 类型转换 ////string msg = "123"; ////int n = (int)msg; //不可以 ////Console.WriteLine(n); ////Console.ReadKey(); //string msg = "123"; //int n = Convert.ToInt32(msg); //Console.WriteLine(n); //可以 //Console.ReadKey(); ////double d = 10; ////Console.WriteLine(d.ToString()); //// ////把任意的字符串转换为数字类型 //string msg = "12345"; ////int n = int.Parse(msg); //int n; //bool b = int.TryParse(msg, out n); // double.TryParse //if (b) //{ // Console.WriteLine(n); //} //else //{ // Console.WriteLine("转换失败!"); //} ////n++; ////Console.WriteLine(n); ////Convert.FromBase64CharArray //Console.ReadKey(); //Console.WriteLine(sizeof(bool));//1 //Console.WriteLine(sizeof(byte));//1 //Console.WriteLine(sizeof(short));//2 //Console.WriteLine(sizeof(int));//4 //Console.WriteLine(sizeof(long));//8 //Console.WriteLine(sizeof(char));//2 //Console.WriteLine(sizeof(float));//4 //Console.WriteLine(sizeof(double));//8 //Console.WriteLine(sizeof(decimal));//16 //Console.ReadKey(); //int n = 100; //char ch = (char)n; //Console.WriteLine(ch); //d //Console.ReadKey(); //char ch = '赵'; //int n = ch; //Console.WriteLine(n); //36213 //Console.ReadKey(); //int n = 10; //double d = n; //Console.WriteLine(d); //int m = (int)d; //Console.WriteLine(m); //Console.ReadKey(); #endregion #region MyRegion //Person p = new DingZhouRen(); //Console.ReadKey(); //DingZhouRen dzr = new DingZhouRen(); //Console.WriteLine(dzr.GetType().ToString()); //DingZhouRen //Console.WriteLine(dzr.GetType().BaseType.ToString()); // BaoDingRen //Console.WriteLine(dzr.GetType().BaseType.BaseType.ToString());//HeBeiRen //Console.WriteLine(dzr.GetType().BaseType.BaseType.BaseType.ToString());//Chinese //Console.WriteLine(dzr.GetType().BaseType.BaseType.BaseType.BaseType.ToString());//Person //Console.WriteLine(dzr.GetType().BaseType.BaseType.BaseType.BaseType.BaseType.ToString());//Object //Console.WriteLine(dzr.GetType().BaseType.BaseType.BaseType.BaseType.BaseType.BaseType.ToString());//错误 //Console.ReadKey(); Person p = new DingZhouRen(); //DingZhouRen dzr = p as DingZhouRen; //if (dzr != null) //{ // Console.WriteLine("ok"); //} //else //{ // Console.WriteLine("类型转换失败!"); //} //输出OK //====================================================== //if (p is DingZhouRen) //{ // DingZhouRen dzr = (DingZhouRen)p; // Console.WriteLine("类型转换成功!"); //} //else //{ // Console.WriteLine("无法进行类型转换!"); //} //类型转换成功! //====================================================== Console.ReadKey(); #endregion } } class Person { } class Chinese : Person { } class HeBeiRen : Chinese { } class BaoDingRen : HeBeiRen { } class DingZhouRen : BaoDingRen { }
异常处理
class Program { static void Main(string[] args) { #region 错误 ////错误! ////1.语法错误。 ////2.逻辑错误。 ////int n = 100; ////int m = 100 - 50; ////Console.WriteLine(m); ////Console.ReadKey(); ////3.运行时错误。 //int apples = 100; //int m = 10; //m = m - 9 - 1; ////除数不能为0,如果为0,则报异常!!! //int r = apples / m; //Console.WriteLine(r); //Console.ReadKey(); #endregion #region 异常处理 //int apples = 100; //int m = 10; //m = m - 9 - 1; ////================== 写多个catch块============================== //try //{ // object o = null; // Console.WriteLine(o.ToString()); // //除数不能为0,如果为0,则报异常!!! // int r = apples / m; // Console.WriteLine(r); //} ////一个try块可以跟多个catch块,这样就可以对不同的异常进行不同的处理。最后可以再加一个catch,参数是Exception ,这样就可以把所有的异常都捕获到了。 //catch (NullReferenceException ex) //{ // Console.WriteLine(ex.Message); //} //catch (DivideByZeroException ex) //{ // Console.WriteLine(ex.Message); //} //catch (ArgumentException ex) //{ // Console.WriteLine(ex.Message); //} //catch (Exception ex) //{ // Console.WriteLine(ex.Message); //} //finally //{ // //执行最终的善后处理,比如资源释放,因为无论程序执行是否发生异常都需要释放资源。 // Console.WriteLine("这里是finally中的代码!!!"); //} //Console.ReadKey(); ////============================================================= //========================================== //try //{ // object o = null; // Console.WriteLine(o.ToString()); // //除数不能为0,如果为0,则报异常!!! // int r = apples / m; // Console.WriteLine(r); //} //catch (Exception ex) //{ // //Exception是所有异常的祖宗类,当在catch中使用Exception的时候,无论什么类型的异常都可以捕获到。 // //对特定的异常进行的处理程序 // Console.WriteLine("异常了。。。" + ex.Message); //} //finally //{ // //执行最终的善后处理,比如资源释放,因为无论程序执行是否发生异常都需要释放资源。 // Console.WriteLine("这里是finally中的代码1!!!"); //} //========================================== //======================================= //try //{ // //除数不能为0,如果为0,则报异常!!! // int r = apples / m; // Console.WriteLine(r); //} //catch //{ // //对特定的异常进行的处理程序 // Console.WriteLine("异常了。。。"); //} //finally //{ // //执行最终的善后处理,比如资源释放,因为无论程序执行是否发生异常都需要释放资源。 // Console.WriteLine("这里是finally中的代码1!!!"); //} //=========================================== //Console.ReadKey(); #endregion #region try-catch-finally使用结构 //try //{ // //可能出现异常的代码!! // //在try块中的代码,如果一旦某句代码发生了异常,这从该条语句直接跳转到catch 块中,在try 块中该条语句后续的代码不会继续执行了。 //} //catch //{ // //当try块中的代码发生异常后,执行这里的代码 // //如果try块中的代码没有发生异常,这不会执行catch 块中的代码 //} //finally //{ // //无论try块中的代码是否发生异常,都会执行这里的代码 //} #endregion ////M2(); //while (true) //{ // Console.WriteLine("请输入一个姓名:"); // string name = Console.ReadLine(); // //一般最好使用if-else等这些逻辑判断,避免使用异常。使用异常效率不高。 // if (name.StartsWith("张")) // { // //手动抛出一个异常。 // throw new Exception("不能是姓张的。"); // } // else // { // Console.WriteLine("姓名是:" + name); // } //} //Console.WriteLine("ok"); //Console.ReadKey(); //int n = 10, m = 0; //try //{ // int r = n / m; // Console.WriteLine(r); //} //catch (Exception e) //{ // Console.WriteLine(e.Message); //} //finally //{ // //Console.WriteLine("finally中的代码。。。。。。。。"); //} //Console.WriteLine("finally中的代码。。。。。。。。"); //Console.ReadKey(); } static void M2() { Console.WriteLine("=============="); try { M1(); } catch { Console.WriteLine("M2方法中的catch块。。。。"); //throw; } Console.WriteLine("=============="); } static void M1() { int n = 100, m = 0; try { int r = n / m; Console.WriteLine(r); } catch (Exception ex) { Console.WriteLine(ex.Message); //这种用写法表示把当前异常样继续向上抛。 // throw; 这种写法只能在catch块中才能这么写。 throw; } finally { //这里的代码能不能不写在finally中? //Console.WriteLine("M1方法的finally中的代码。。。"); } //如果在catch块中使用了throw,则后面的代码如果不放在finally中,就不会执行。 //Console.WriteLine("M1方法的finally中的代码。。。"); //手动抛出一个异常。 //throw new Exception(); } }
代码异常检测
class Program { static void Main(string[] args) { //T1(); //int n = GetNumber(); //Console.WriteLine("返回值:{0}", n); //Console.ReadKey(); //当没有异常发生的时候,返回结果是101,并且finally中的代码执行了. //当发生异常的时候,返回结果是102,finally中的代码同样也执行了。 //int r = M1(); //Console.WriteLine(r); //Console.ReadKey(); //Person p1 = GetPerson(); //Console.WriteLine(p1.Age);//103 //Console.ReadKey(); } static Person GetPerson() { Person p = new Person(); p.Age = 100; try { p.Age = p.Age + 1; //======引发异常的代码========== int x = 10, y = 0; Console.WriteLine(x / y); //======引发异常的代码========== return p; } catch (Exception) { p.Age = p.Age + 1; return p; } finally { p.Age = p.Age + 1; } } static int M1() { int result = 100; try { result = result + 1; //======引发异常的代码========== int x = 10, y = 0; Console.WriteLine(x / y); //======引发异常的代码========== return result; } catch { result = result + 1; return result; } finally { result = result + 1; } } static int GetNumber() { try { int n1 = 10; int n2 = 0; //======引发异常的代码========== int n3 = n1 / n2; //======引发异常的代码========== return 100; } catch (Exception ex) { Console.WriteLine("*******异常了*********"); return 1000; } finally { Console.WriteLine("finally中的代码!!!!"); } } static void T1() { try { Console.WriteLine("11111111111111111111"); //====引发异常代码===== int n = 10, m = 0; Console.WriteLine(n / m); //====引发异常代码===== Console.WriteLine("★★★★★★★★★★★★★★"); return; Console.WriteLine("22222222222222222222"); } catch (Exception) { Console.WriteLine("33333333333333333333"); } finally { //虽然try块中有return语句,但是finally中的代码依然会执行,并且是在return 语句之前执行的。 Console.WriteLine("4444444444444444444444"); } } } class Person { public int Age { get; set; } }
参数修饰符
class Program { static void Main(string[] args) { #region 可变参数 ////int r = Add(1, 2, 3, 4, 5, 6, 76, 78, 8); //int[] arr = new int[] { 1, 3, 5, 7, 9 }; //int r = Add(arr); ////int r = Add(10, 10); //Console.WriteLine(r); //Console.ReadKey(); //Console.WriteLine("{0} {1} {2} {3}", 1, 2, 3, 4); //string.Format( #endregion #region ref ////int x = 10; //int x = 100; ////ref参数在传递的时候必须为变量赋值。 //M1(ref x); //101 //Console.WriteLine(x); //Console.ReadKey(); //int salary = 100000; //JiangJin(ref salary); //JiXiao(ref salary); //QuanQinJiang(ref salary); //ChiDao(ref salary); //Console.WriteLine(salary); //Console.ReadKey(); #endregion #region out //int n; ////out参数在传递之前完全没有必要赋值,即便赋值了也没有任何意义,在方法中 ////使用之前必须重新赋值,才能使用,out参数无法将变量的值,从方法外面传递进来。 //TestOut(out n); //Console.WriteLine(n); //Console.ReadKey(); ////M2( #endregion } static void M2(int n) { } ////static void M2(ref int n) ////{ ////} //static void M2(out int n) //{ //} //out参数的主要作用就是,当方法有多个返回值的时候,可以通过out参数来获取方法的多个返回值。 static void TestOut(out int m) { //既然out参数无法把方法外的变量值传递进来,所以在方法中必须为out参数赋值后才能使用 //m = 100; //m = m + 100; //out参数要求在方法中必须为该参数赋值!!!!! m = 100; } private static void ChiDao(ref int salary) { salary = salary - 5 * 200; } private static void QuanQinJiang(ref int salary) { salary = salary + 500; } private static void JiXiao(ref int salary) { salary = salary + 300; } private static void JiangJin(ref int salary) { salary = salary + 10000; } static void M1(ref int n) { //在方法中可以直接使用ref变量的值,并且在方法中不为该变量赋值也是完全可以的。 n++; } //如果传递多个参数,这每个参数都是nums数组中的一个元素,如果一个参数都不传递,这nums并不是null,而是一个长度为0的数组。 //使用可变参数要注意: //1.参数使用pramas关键字修饰 //2.参数的类型是一个数组类型 //3.如果该方法有多个参数,这可变参数必须写在最后一个。 //4.可变参数也可以直接传递一个数组进来。 static int Add(params int[] nums) { int sum = 0; for (int i = 0; i < nums.Length; i++) { sum += nums[i]; } return sum; } static int Add(int n1, int n2) { return n1 + n2; } static int Add(int n1, int n2, int n3) { return n1 + n2 + n3; } }
ref与out练习
class Program { static void Main(string[] args) { #region 案例1:两个int变量的交换,用方法做。ref //int n1 = 10, n2 = 20; //Swap(ref n1, ref n2); //Console.WriteLine("n1={0},n2={1}", n1, n2); //n1=20 ,n2=10 //Console.ReadKey(); #endregion #region 案例2:模拟登陆,返回登陆是否成功(bool),如果登陆失败,提示用户是用户名错误还是密码错误”admin”,“888888” while (true) { Console.WriteLine("请输入用户名:"); string loginId = Console.ReadLine(); Console.WriteLine("请输入密码:"); string loginPwd = Console.ReadLine(); string message; bool isOk = CheckUserLogin(loginId, loginPwd, out message); Console.WriteLine("登录结果:{0} 提示消息:{1}", isOk, message); } #endregion } private static bool CheckUserLogin(string loginId, string loginPwd, out string message) { message = string.Empty; if (loginId == "admin" && loginPwd == "888888") { message = "登录成功!"; return true; } else if (loginId == "admin") { message = "密码错误!"; return false; } else { message = "用户名错误!"; return false; } } private static void Swap(ref int n1, ref int n2) { int t = n1; n1 = n2; n2 = t; } }