c# 基础语法

c# 程序结构

using System.Collections.Generic;
namespace demo1;  //一个命名空间可以包含多个类
using System.IO;
using System.Drawing;

class proj
{
    /// 
    /// c#是微软开发的,基于c和c++的一种面象对象编程语言,用于快速开发windows桌面应用
    /// c#和java类似,但是c#主要是桌面应用开发,而java主要是面象web应用开发
    /// 

    //定义一个类
    class rectangel
    {
        // 属性
        double length;
        double width;
        //方法
        public void Acceptdetails()
        {
            this.length = 4.5;
            this.width = 2;
        }
        public double getArea()
        {
            return this.length*this.width;
        }
        public void Display()
        {
            Console.WriteLine("Length{0}",this.length);
            Console.WriteLine("width{0}", this.width);
            Console.WriteLine("area{0}",getArea());

        }
    }

    //Main函数是程序的主入口,且必须是静态的
    internal static void Main(string[] args)
    {
        //声明一个对象
        rectangel a = new rectangel();
        a.Acceptdetails();
        a.Display();

        //阻塞窗口
        Console.ReadLine();
       

    }
}


c#数据类型与变量

基本数据类型

namespace demo1;  

class proj
{
   
   /// 基本数据类型:
   /// bool 布尔值
   /// byte 8位无符号整数
   /// char 16位Unicode字符
   /// decimal 128精确的十进制值
   /// double 64位浮点型
   /// float 32位单精度浮点型
   /// int 32位有符号整数
   /// long 64位有符号整数
   /// sbyte 8位有符号整数
   /// uint 32位无符号整数
   /// ulong 64位
   /// ushort 16位
      
     
    internal static void Main(string[] args)
    {
        //1.基本数据类型:分配存储空间,存放数据
        int Int_number = 1;
        double Double_number = 3.14;
        bool Bool_number = true;
        Console.WriteLine("Int: {0},Double: {1},Bool: {2}", Int_number, Double_number, Bool_number);//自动换行

    }
}


引用数据类型

namespace demo1;  

class proj
{
   /// 引用数据类型:不存放实际的数据,而是存放数据的位置
   /// 引用数据类型的数据存放在堆上,引用存放在栈上
   /// 内置的引用数据类型有:object ,string,自定义的类

     
    internal static void Main(string[] args)
    {
        String str = "hello world";
        string str_origin = "hello\nworld";// 转义字符
        string str_change= @"hello\nworld";

        Console.WriteLine(str);
        Console.WriteLine(str_origin);
        Console.WriteLine(str_change);

    }
}


数据类型转换

namespace demo1;  

/// 
/// 数据类型转换:
/// 1 隐式类型转换:安全转换,不会造成数据丢失
/// 2 显示类型转换:不安全转换,会造成数据丢失
/// 3 内置的类型转换: int.Parse() ToString()
/// 
class proj
{

    internal static void Main(string[] args)
    {
        double a = 3.1412;
        int b=(int)a; //向下取整,丢失精度
        Console.WriteLine(b);
        //内置的类型转换方法
        string num = "66";
        Console.WriteLine("int -> string {0}",a.ToString());
        Console.WriteLine("string -> int {0}",int.Parse(num));

        int c=Convert.ToInt32(num); //将字符转换为int
        string d = Convert.ToString(a);

        Console.WriteLine(d);
        Console.WriteLine(c);
        

    }
}


字符串类型

namespace demo1;

/// 
/// 字符串:使用string 关键字来声明一个字符串变量,string是systerm.sting类的别名
/// 字符串常用方法:
/// 1 public static int Compare( string strA, string strB ):比较两个指定的 string 对象(按ASCII),并返回一个表示它们在排列顺序中相对位置的整数
/// 2 public static string Concat( string str0, string str1 ):连接两个 string 对象。相当于+
/// 3  public bool Contains( string value ):判断字符串是否包含字串value
/// 4 public bool EndsWith( string value ):判断 string 对象是否以value结尾
/// 5 public bool StartsWith( string value ):判断字符串实例的开头是否匹配指定的字符
/// 6 public bool Equals( string value ):判断当前的 string 对象是否与指定的 string 对象具有相同的值
/// 7 public static string Format( string format, Object arg0 ):把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式
/// 8 public int IndexOf( string value/char ch ):返回指定字符串在该实例中第一次出现的索引,索引从 0 开始
/// 9 public int LastIndexOf( string value/char value ):返回指定字符串在该实例中最后一次出现的索引,索引从 0 开始
/// 10 public string Insert( int startIndex, string value ):返回一个新的字符串,其中,指定的字符串被插入在当前 string 对象的指定索引位置
/// 11 public static string Join( string separator, string[] value ):连接一个字符串数组中的所有元素,使用指定的分隔符分隔每个元素
/// 12 public string Remove( int startIndex ):移除当前实例中的所有字符,从指定位置开始,一直到最后一个位置为止,并返回字符串
/// 13 public string Replace( string oldValue, string newValue ):把当前 string 对象中,所有指定的字符串替换为另一个指定的字符串,并返回新的字符串
/// 14 public string[] Split( params char[] separator ):返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的
/// 

class proj
{

    internal static void Main(string[] args)
    {
        // 字符串的构建
        string a = "hello";
        string b = "world";
        //string c = "hello world";
        string c=string.Concat(a, b);
        string d = a + b;

        //1 字符串比较
        Console.WriteLine("字符串比较 compare:{0} {1},equal:{2}",string.Compare(a,b),a.CompareTo(b),a.Equals(b));
        Console.WriteLine("字符串a是否以h开头{0}",a.StartsWith("h"));
        //字符串的查找
        Console.WriteLine("字符串a中查找第一次出现h{0}",a.IndexOf("h"));
        Console.WriteLine("字符串c中查找最后次出现l{0}", c.LastIndexOf("l"));

        //字符串的增加
        Console.WriteLine("a+hello {0}",a.Insert(5," hello"));

        //定义一个字符串数组
        string[] f  = { "hello", "world", "sun" };
        string g = "hello wold 你好";
        string[] h = g.Split(" ");
        foreach(string s in h)
        {
            Console.WriteLine(s);
        }
        


    }
}


分支语句和循环语句

namespace demo1;


class proj
{

    internal static void Main(string[] args)
    {
        
        for (int i= 0; i<10;i++)
        {
            if (i%2==0)
            {
                Console.WriteLine("{0}是偶数",i);
            }
            else { Console.WriteLine("{0}是奇数",i); }
        }
  
        


    }
}


c# 数组

可空类型

namespace demo1;

/// 
/// 可空类型(null):表示在基础值类型正常范围内的值
/// 单问号 是对int double bool无法正常赋值的数据进行赋值
/// 双问号 
/// 
class proj
{
    
    internal static void Main(string[] args)
    {
        int? num1 = null;//声明可空类型
        Console.WriteLine("可空类型{0}",num1);
        num1 = 10;
        Console.WriteLine(num1);

        int? num2 = null;
        if (num2==null)
        {
            Console.WriteLine("num2是可空类型");
        }
        else
        {
            Console.WriteLine("num2不是可空类型");
        }

        //null 合并运算符(??):判断如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值

        double? b= null;
        double? c= 3.13;
        double? a = b ?? c;//如果b是可空则c,否则为b
        Console.WriteLine(a);


    }
}


数组

namespace demo1;
/// 
/// 数组是存储相同类型的固定大小的集合
/// 声明数组:double[] arrays;
/// 初始化数组: double[] arrays=new double[10]
/// 数组是一个引用类型,所以需要声明一个数组的实例
/// 数组赋值:
///     索引赋值:arrays[0]=3.13
///     声明时候同时赋值 double[] arrays=new double[10]{1,2,3,4,5,6,7,8,9,10}
/// 数据访问: 遍历 [] 下标访问 foreach循环
/// 
/// 多维数组;int[10,10] 声明一个10行10列的数组
/// 交错错组:交错数组是数组的数组
/// 

class proj
{
    
    internal static void Main(string[] args)
    {
      int[] List=new int[10]; //声明一个数组
        for (int i = 0; i < List.Length; i++) 
        {
            //为数组赋值
            List[i] = i*2;
        }
        //打印数组元素
        Console.WriteLine("打印数组元素");
        foreach(int i in List)
        {  Console.WriteLine(i); }

        //多维数组
        Console.WriteLine("多维数组");

        int[,] matrix = new int[3, 4]
        {
            {0,1,2,3 },
            { 4,5,6,7},
            { 8,9,10,11},
        }; //初始化多维数组并且赋值

        //x循环遍历多维数组
        Console.WriteLine("打印多维数组");
        for (int i = 0; i < matrix.GetLength(0); i++)
        {
            for (int j=0;j<matrix.GetLength(1);j++)
            {
                Console.WriteLine("矩阵{0} {1}值为{2}", i, j, matrix[i,j]);
            }
        }

        //交错数组
        int[][] scores = new int[5][];
        for (int i = 0;i < scores.Length; i++)
        {
            if (i<=2)
            {
                scores[i] = new int[3];
            }
            else
            {
                scores[i] = new int[4];
            }
            //赋值
            for(int j = 0; j < scores[i].Length;j++)
            {
                scores[i][j] = i * j + 6;

            }
        }

        //
        Console.WriteLine("打印交错数组");
        for (int i = 0;i<scores.Length;i++)
        {
            for (int j = 0; j < scores[i].Length;j++)
            {
                Console.WriteLine("子数组{0}下标{1}的值{2}", i, j, scores[i][j]);
            }
        }
    }
}


namespace demo1;
/// 
/// Array类,Array类是c#所有数组的基类
/// 

class proj
{
    
    internal static void Main(string[] args)
    {

        int[] list = { 34, 72, 13, 25 };
        Console.WriteLine("原始数组");
        for (int i = 0; i < list.Length; i++) 
        {
            Console.Write(list[i]);
        }
        Console.WriteLine();
        Array.Reverse(list);
        Console.WriteLine("逆转数组");
        for (int i = 0; i < list.Length; i++)
        {
            Console.Write(list[i]+"\t");
        }
        Console.WriteLine();
        Console.WriteLine("排序数组");
        Array.Sort(list);

        for (int i = 0; i < list.Length; i++)
        {
            Console.Write(list[i]+"\t");
        }
        Console.WriteLine();





    }
}


c#列表与字典

列表arrayList

using System.Collections;

namespace demo1;
/// 
/// ArrayList 动态数组列表
/// 初始化 ArrayList是一个类/对象,需要使用new关键字初始化,且不需要指定大小(动态扩展) ArrayList array = new ArrayList();
/// 使用:
///     1 Item[12] 获取指定索引的元素
///     2 Count 获取实际元素个数
///     3 public virtual int Add( object value ); 在 ArrayList 的末尾添加一个对象
///     4 public virtual void Clear(); 从 ArrayList 中移除所有的元素。
///     5 public virtual void Insert( int index, object value ); 在 ArrayList 的指定索引处,插入一个元素。
///     6 public virtual void Remove( object obj ); 从 ArrayList 中移除第一次出现的指定对象
/// 

class proj
{
    
    internal static void Main(string[] args)
    {
        ArrayList arrayList = new ArrayList();
        arrayList.Add(2);
        arrayList.Add(3.1415);
        arrayList.Add("hello world");
        Console.WriteLine("ArrayList 长度: " + arrayList.Count);
        Console.WriteLine("ArrayList[0]: " + arrayList[0]);
        Console.WriteLine("ArrayList[1]: " + arrayList[1]);
        Console.WriteLine("ArrayList[2]: " + arrayList[2]);
        Console.ReadKey();

    }
}


列表List

using System.Collections;

namespace demo1;
    //2.List:List也是一种动态列表集合,类似于ArrayList,但必须提供泛型
    //  (1)定义:为了解决ArrayList的类型不安全,C#提供了List列表,List列表声明时必须提供泛型,即List内存放的数据必须都是该泛型的数据。
    //  (2)初始化:List list = new List();
    //  (3)本质:List其实就是在ArrayList基础上,添加了类型限制,以后都推荐使用List
    //  (4)使用:与ArrayList类似,注意泛型也可以是自定义的类,List也可以存放对象!


class proj
{
    
    internal static void Main(string[] args)
    {
        List<int> list = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            list.Add(i + 1);
        }
        for (int i = 0; i < list.Count; i++)
        {
            if (list[i] % 2 != 0)
            {
                list[i] *= 2;
            }
        }
        foreach (int val in list)
        {
            Console.Write(val + " ");
        }
        Console.WriteLine();
        list.Clear();
        Console.WriteLine("清空后长度 : " + list.Count);
        Console.ReadLine();


    }
}


字典 Dictionary

using System.Collections;

namespace demo1;
    //3.Dictionary:Dictionary是由键值对组成的字典类型,类似于Java的Map
    //  (1)初始化:Dictionary也是对象,需要使用new关键字。同时在初始化时需要指定键值对的泛型 Dictionary dir = new Dictionary();
    //  (2)特点:
    //      - Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值),可以通过 Dictionary[key]来取值
    //      - Dictionary里面键必须是唯一的,而值不需要唯一的
    //  (3)使用:
    //      - Count        获取包含在 Dictionary 中的键/值对的数目。
    //      - Keys         获取包含 Dictionary 中的键的集合。
    //      - Values 获取包含 Dictionary 中的值的集合。
    //      - Add                 将指定的键和值添加到字典中。
    //      - Clear 从 Dictionary 中移除所有的键和值。
    //      - ContainsKey 确定 Dictionary 是否包含指定的键。
    //      - GetEnumerator       返回循环访问 Dictionary 的枚举器
    //      - Remove              从 Dictionary 中移除所指定的键的值。

class proj
{
    
    internal static void Main(string[] args)
    {
        Dictionary<string, int> dictionary = new Dictionary<string, int>();
        dictionary.Add("wangxin", 99);//Add赋值,Add赋值不能添加key重复的项
        dictionary["shayuan"] = 100;//=赋值,=赋值可以添加key重复项,会覆盖原始数据
        if (dictionary.ContainsKey("wangxin"))//是否包含key
        {
            Console.WriteLine("Dictionary 长度: " + dictionary.Count);
            Console.WriteLine("wangxin is {0}", dictionary["wangxin"]);
            dictionary.Remove("wangxin");//删除key
        }
        if (dictionary.ContainsKey("shayuan"))
        {
            Console.WriteLine("Dictionary 长度: " + dictionary.Count);
            Console.WriteLine("shayuan is {0}", dictionary["shayuan"]);
        }
        //Console.WriteLine("wangxin is {0}", dictionary["wangxin"]);//访问不存在的数据会报异常
        if (!dictionary.ContainsKey("wangxin"))
        {
            Console.WriteLine("wangxin is removed!");
        }
        //遍历Dictionary
        //遍历key
        foreach (string key in dictionary.Keys)
        {
            Console.WriteLine("Key = {0}", key);
        }
        //遍历value
        foreach (int value in dictionary.Values)
        {
            Console.WriteLine("value = {0}", value);
        }
        //遍历字典
        foreach (KeyValuePair<string, int> kvp in dictionary)
        {
            Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
        }

        //添加存在的元素 try...catch..处理异常
        try
        {
            dictionary.Add("txt", 99);
        }
        catch (ArgumentException)
        {
            Console.WriteLine("An element with Key = \"txt\" already exists.");
        }
        Console.ReadKey();


    }
}


类与继承


namespace netBasic_learning
{
    //1.类的封装
    //  (1)访问修饰符:类的默认访问标识符是 internal,成员的默认访问标识符是 private。
    //      - public:所有对象都可以访问;
    //      - private:对象本身在对象内部可以访问;
    //      - protected:只有该类对象及其子类对象可以访问
    //      - internal:同一个程序集的对象可以访问;可以被定义在该成员所定义的【应用程序内】的任何类或方法访问。
    //      - protected internal:访问限于当前程序集或派生自包含类的类型。(protected和internal的并集)
    //  (2)方法:类的行为,主要是方法参数的传递方式
    //      - 值传递:这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。在这种情况下,当形参的值发生改变时,不会影响实参的值
    //      - 引用传递(ref):这种方式复制参数的内存位置的引用给形式参数。这意味着,当形参的值发生改变时,同时也改变实参的值。
    //      - 输出参数(out):这种方式可以返回多个值。传 out 定义的参数进去的时候这个参数在函数内部必须初始化。否则是不能进行编译的。
    //      - 数组传值:可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针。
    //  注意:ref 和 out 都是传递数据的地址,正因为传了地址,才能对源数据进行修改。
    class A
    {
        public int _a;
        public int _b;
        //值传递
        public void sum(int a, int b)
        {
            a += b;
            Console.WriteLine("值传递函数内求和 a = {0}", a);
        }
        //引用传递
        public void sum(ref int a, ref int b)
        {
            a += b;
            Console.WriteLine("引用传递函数内求和 a = {0}", a);
        }
        //输出参数
        public void sum(int a, int b, out int c)
        {
            c = a + b;
        }
        //类/对象传递(对象传值 = 引用传值)
        public void swap(A obj)
        {
            int temp = obj._a;
            obj._a = obj._b;
            obj._b = temp;
        }
        //数组传值
        public void sumAndClear(int[] arrays)
        {
            int sum = 0;
            for (int i = 0; i < arrays.Length; i++)
            {
                sum += arrays[i];
                arrays[i] = 0;
            }
            Console.WriteLine("数组求和sum = {0}", sum);
        }

        public static void Main(string[] args)
        {
            A a_obj = new A();
            //值传递
            int a = 3, b = 4;
            Console.WriteLine("值传递求和前初始数据a = {0},b = {1}", a, b);
            a_obj.sum(a, b);
            Console.WriteLine("值传递求和后初始数据a = {0},b = {1}", a, b);
            //引用传递
            Console.WriteLine("引用传递求和前初始数据a = {0},b = {1}", a, b);
            a_obj.sum(ref a, ref b);
            Console.WriteLine("引用传递求和后初始数据a = {0},b = {1}", a, b);
            //输出参数
            int res;
            Console.WriteLine("输出参数求和前初始数据a = {0},b = {1}", a, b);
            a_obj.sum(a, b, out res);
            Console.WriteLine("引用传递求和后初始数据a = {0},b = {1},res = {2}", a, b, res);
            //对象传递
            a_obj._a = 3;
            a_obj._b = 4;
            Console.WriteLine("对象传递交换前初始数据a = {0},b = {1}", a_obj._a, a_obj._b);
            a_obj.swap(a_obj);
            Console.WriteLine("对象传递交换后初始数据a = {0},b = {1}", a_obj._a, a_obj._b);
            //数组传递
            int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Console.Write("数组传值前: ");
            foreach (int fac in arr) Console.Write(fac + " ");
            Console.WriteLine();
            a_obj.sumAndClear(arr);
            Console.Write("数组传值后: ");
            foreach (int fac in arr) Console.Write(fac + " ");
            Console.ReadLine();
        }
    }
}
namespace demo1;
//2.类的基本参数
//  (1)构造函数:初始化对象时自动执行,默认提供一个无参构造 Object(){}
//  (2)析构函数:销毁对象时自动执行 ~Object(){}
//  (3)静态成员变量: static 关键字把类成员定义为静态的,静态成员变量属于类,可以在任意地方初始化和使用
//  (4)静态成员函数:static 关键字把类成员定义为静态的,静态成员变量属于类,静态成员函数只能访问静态变量
class B
{
    public static int cnt = 0;
    private double val;
    public B()
    {
        val = 0;
        cnt++;
        Console.WriteLine("第{0}个B,无参构造函数Val = {1}", cnt, val);
    }
    public B(double _val = 0)
    {
        val = _val;
        cnt++;
        Console.WriteLine("第{0}个B,有参构造函数Val = {1}", cnt, val);
    }
    public double getVal()
    {
        return this.val;
    }
    public static int getCntOfB()
    {
        return cnt;
    }

    ~B()
    {
        cnt--;
        Console.WriteLine("析构函数执行");
    }

    public static void Main(string[] args)
    {
        B b_1 = new B();
        Console.WriteLine(b_1.getVal());
        B b_2 = new B(3.14);
        Console.WriteLine(b_2.getVal());
        Console.WriteLine(B.getCntOfB());
        Console.ReadKey();
    }

}
 

继承


namespace netBasic_learning
{
    //3.类的继承 Child:Parent
    //  (1)C#只支持单继承,但可以通过接口来实现多继承
    //  (2)派生类继承了基类的public、protected、internal成员变量和成员方法。
    //  (3)若不指明,创建子类对象调用子类的构造函数时,会默认首先调用父类的无参构造函数
    class Shape
    {
        protected double length;
        protected double width;
        public Shape(double len, double wid)
        {
            length = len;
            width = wid;
        }
        public double GetArea()
        {
            return length * width;
        }
        public void Display()
        {
            Console.WriteLine("长度: {0}", length);
            Console.WriteLine("宽度: {0}", width);
            Console.WriteLine("面积: {0}", GetArea());
        }
    }

    class Cube : Shape
    {
        private double height;
        public Cube(double len, double wid, double hei) : base(len, wid)//base(x,y)初始化父类参数,先于子类执行
        {
            height = hei;
        }
        public double GetVolume()
        {
            return height * GetArea();
        }
        public void Display()
        {
            base.Display();//通过base来指代当前对象的父类
            Console.WriteLine("体积: {0}", GetVolume());
        }
        public static void Main(string[] args)
        {
            Cube cube = new Cube(2, 3, 4);
            cube.Display();//调用子类的覆盖方法
            Console.ReadKey();
        }
    }
}

多态

namespace netBasic_learning
{
    //1.多态:多态是根据不同的场景同一个行为具有多个不同表现形式或形态的能力。
    //  (1)静态多态:函数的响应是在编译时发生的。
    //      - 函数重载:对相同的函数名有多个定义。可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
    //      - 运算符重载:可以重定义或重载 C# 中内置的运算符。通过关键字 operator 后跟运算符的符号来定义的,同时包含 public 和 static 修饰符。
    class Vector
    {
        private int x;
        private int y;
        public Vector()
        {
            x = 0;
            y = 0;
        }
        public Vector(int _x, int _y)
        {
            x = _x;
            y = _y;
        }

        public int getX() { return x; }
        public int getY() { return y; }
        public void setX(int x) { this.x = x; }
        public void setY(int y) { this.y = y; }
        public void Display()
        {
            Console.WriteLine("Vector({0},{1})", x, y);
        }

        // 重载 + 运算符来把两个 Vector 对象相加(可以直接访问private)
        public static Vector operator +(Vector a, Vector b)
        {
            Vector C = new Vector();
            C.x = a.x + b.x;
            C.y = a.y + b.y;
            return C;
        }

        // 重载 - 运算符来把两个 Vector 对象相减(可以直接访问private)
        public static Vector operator -(Vector a, Vector b)
        {
            Vector C = new Vector();
            C.x = a.x - b.x;
            C.y = a.y - b.y;
            return C;
        }

        // 重载 * 运算符来把两个 Vector 对象相乘(可以直接访问private)
        public static int operator *(Vector a, Vector b)
        {
            return a.x * b.x + a.y * b.y;
        }

        public static void Main(string[] args)
        {
            Vector a = new Vector(2, 3);
            Vector b = new Vector(3, 4);
            //+法
            Vector c = a + b;
            c.Display();
            //-法
            c = a - b;
            c.Display();
            //*法
            int res = a * b;
            Console.WriteLine(res);
            Console.ReadKey();
        }
    }
}
namespace netBasic_learning
{
    //动态多态:函数的响应是在运行时发生的。
    //      - 虚方法(virtual ):定义子类可以重写覆盖父类的方法,对虚方法的调用是在运行时发生的。子类需要使用override声明
    //          + 父类定义虚方法,子类可以实现重写父类虚方法,也可以不实现重写。如果重写了,那么创建子类对象后,不管是父类指针还是子类,调用虚方法都会执行子类的覆盖。
    //          + 父类定义虚方法,必须要有父类的实现,在父类中是一个普通函数。
    //      - 抽象(abstract ):抽象abstract关键字可以作用在方法上,也可以作用在类上。子类需要使用override声明
    //          + 父类抽象方法没有实现,只有声明。子类必须实现父类的抽象方法
    //          + 类内任何一个方法是抽象的,则该类必须被声明为抽象类。即抽象方法只能在抽象类中定义
    //          + 抽象类不能被实例化,但可以指向子类实例。子类若不实现抽象方法则也会变成抽象类。
    //      - 总结:简单说,抽象方法是需要子类去实现的。虚方法是已经实现了的,可以被子类覆盖,也可以不覆盖,取决于需求。抽象方法和虚方法都可以供派生类重写。
    abstract class Animal
    {
        //抽象类:包含至少一个抽象方法,但是不仅仅包含抽象方法
        protected string name;
        public Animal(string _name)
        {
            name = _name;
        }

        //抽象方法:叫
        abstract public void shout();

        //虚方法
        virtual public void eat()
        {
            Console.WriteLine("{0} is eating", name);
        }
    }

    class Dog : Animal
    {
        public Dog(string name) : base(name)
        {

        }
        //实现抽象类
        public override void shout()
        {
            Console.WriteLine("A Dog {0} is wangwang", name);
        }

        //覆盖重写虚函数
        public override void eat()
        {
            base.eat();
            Console.WriteLine("A Dog {0} is eat bone", name);
        }
    }

    class Cat : Animal
    {
        public Cat(string name) : base(name)
        {

        }
        //实现抽象类
        public override void shout()
        {
            Console.WriteLine("A Cat {0} is miaomiao", name);
        }

        //覆盖重写虚函数
        public override void eat()
        {
            base.eat();
            Console.WriteLine("A Cat {0} is eat fish", name);
        }

        public static void Main(string[] args)
        {
            Animal[] animals = new Animal[2] { new Dog("tom"), new Cat("marry") };
            foreach (Animal animal in animals)
            {
                animal.shout();
                animal.eat();
            }
            Console.ReadKey();
        }

    }

}

参考:
c#基础语法

你可能感兴趣的:(c#开发,c#,python,开发语言)