C#基础入门第十二天(面向对象多态,File操作流,泛型集合)

复习
static void Main(string[] args)
    {
        /*
         里氏转换
         1、子类赋值给父类(如果有一个父类作为参数,我们可以传递一个子类对象)
         2、如果父类中装的是子类对象,则可以将这个父类强转为子类对象
         */
        // Person p = new Teachar();
        //is
        //if (p is Teachar)
        //{
        //    ((Teachar)p).TeacharSayHello();
        //}
        //else
        //{
        //    Console.WriteLine("转换失败");
        //}
        //Console.ReadKey();

        //as
        //Teachar t = p as Teachar;
        //t.TeacharSayHello();
        //Console.ReadKey();

        //ArrayList list = new ArrayList();
        //方法:Remove RemoveAt RemoveRange Clear Insert  InsertRange Revers Sort

        //Hashtable ht = new Hashtable();
        //ht.Add(1, "张三");
        //ht.Add(true, ‘男‘);
        ////在键值对集合中,键必须是唯一的
        ////ht.Containskey  判断当前是否包含这个键
        //foreach (var item in ht.Keys)
        //{
        //    Console.WriteLine("{0}-------{1}", item, ht[item]);
        //}
        //Console.ReadKey();

        //两个类都是静态类
        //Path类:

        //File类:文本文件进行读写
        //byte[] buffer = File.ReadAllBytes(@"C:\Users\Administrator\Desktop\1.txt");
        ////将字节数组中的每一个元素都要按照我们制定的编码格式解码成字符串
        ////UTF-8 GB2312 GBK ASCII Unicode
        //// string s = Encoding.Default.GetString(buffer);
        //string s = Encoding.GetEncoding("gb2312").GetString(buffer);
        //Console.WriteLine(s);

        //如果没有这个文件,系统会创建一个,有就覆盖
        string str = "今天天气不错,挺风和日丽的";
        byte[] buffer = Encoding.Default.GetBytes(str);
        File.WriteAllBytes(@"C:\Users\Administrator\Desktop\2.txt",buffer);
        Console.WriteLine("写入成功");
        Console.ReadKey();
    }
}

public class Person
{
    public void PersonSayHello()
    {
        Console.WriteLine("我是人类");
    }
}
public class Teachar : Person
{
    public void TeacharSayHello()
    {
        Console.WriteLine("我是老师类");
    }
}

十二天新内容
一、绝对路径和相对路径
绝对径路:通过给定的这个路径直接能在我的电脑中找到这个文件
相对路径:文件相对于应用程序的路径
开发中尽量使用相对路径
File类最大的缺点:只能读取小文件,因为浪费内存

static void Main(string[] args)
    {
        // //以行的形式读取  需要操作每行数据用这个
        //string[] s = File.ReadAllLines(@"C:\Users\Administrator\Desktop\1.txt");
        // foreach (string item in s)
        // {
        //     Console.WriteLine(item);
        // }
        // Console.ReadKey();

        // //拿到是一个字符串
        //string str = File.ReadAllText("1.txt", Encoding.Default);
        //Console.WriteLine(str);
        //Console.ReadKey();

        //File.WriteAllLines(@"C:\Users\Administrator\Desktop\1.txt", new string[] { "a", "o", "e" });
        //Console.WriteLine("写入成功");
        //Console.ReadKey();

        //File.WriteAllText(@"C:\Users\Administrator\Desktop\1.txt",  "aoeiuv");
        //Console.WriteLine("写入成功");
        //Console.ReadKey();

        //新增写入,不覆盖之前的内容
        File.AppendAllLines(@"C:\Users\Administrator\Desktop\1.txt", new string[] { "有", "没", "有" });
        Console.WriteLine("OK");
        Console.ReadKey();
    }

二、List泛型集合
语法及方法

static void Main(string[] args)
    {
        //创建泛型集合对象
        List<int> list = new List<int>();
        list.Add(1);
        list.Add(2);
        list.AddRange(new int[] { 1,2,3,40});
        list.AddRange(list);

        //List泛型集合可以转换为数组
        int[] num = list.ToArray();

        List<string> listStr = new List<string>();
        string[] str = listStr.ToArray();

        //数组转为List泛型集合
        List<int> listTwo = num.ToList();

        char[] chs = new char[] { ‘a‘, ‘b‘, ‘c‘ };
        List < char > listChar= chs.ToList();

        for (int i = 0; i < list.Count; i++)
        {
            Console.WriteLine(list[i]);
        }
        Console.ReadKey();
    }

装箱、拆箱
装箱:就是将值类型转换为引用类型
拆箱:将引用类型转换为值类型
看两种类型是否发生了装箱或拆箱,要看,这两种类型是否存在继承关系

static void Main(string[] args)
    {
        int n = 10;
        object o = n;//装箱
        int nn = (int)o;//拆箱

        //下面的代码并没有发生装箱或者拆箱
        //看两种类型是否发生了装箱或拆箱,要看,这两种类型是否存在继承关系,有继承关系则偶可能发生装箱拆箱,没有继承则不发生,以下代码则不会发生
        string str = "123";
        int n1 = Convert.ToInt32(str);
    }

三、Dictionary键值对集合(字典集合)
语法及方法

static void Main(string[] args)
    {
        //创建Dictionary
        Dictionary<int, string> dic = new Dictionary<int, string>();
        dic.Add(1, "张三");
        dic.Add(2, "李四");
        dic.Add(3, "王五");
        dic[1] = "新来的";
        //foreach (var item in dic.Keys)
        //{
        //    Console.WriteLine("{0}--------{1}", item, dic[item]);
        //}

        //一对数据一对数据的遍历  尽量多使用这种遍历
        foreach (KeyValuePair<int,string> kv in dic)
        {
            Console.WriteLine("{0}--------{1}", kv.Key, kv.Value);
        }
        Console.ReadKey();
    }

集合的三个练习

static void Main(string[] args)
    {
        ////将一个数组中的奇数放到一个集合中,偶数放到另一个集合中
        ////最终将两个集合合并为一个集合,奇数在左边,偶数在右边
        //int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        //List<int> qi = new List<int>();
        //List<int> ou = new List<int>();
        //for (int i = 0; i < nums.Length; i++)
        //{
        //    if (nums[i] % 2 == 0)
        //    {
        //        ou.Add(nums[i]);
        //    }
        //    else
        //    {
        //        qi.Add(nums[i]);
        //    }
        //}
        ////List<int> zheng = new List<int>();
        ////zheng.AddRange(qi);
        ////zheng.AddRange(ou);
        //qi.AddRange(ou);
        //foreach (int item in qi)
        //{
        //    Console.Write(item+" ");
        //}
        //Console.ReadKey();

        ////提示用户输入一个字符串,通过foreach循环将用户输入的字符串赋值给一个字符数组。
        //Console.WriteLine("请输入一段字符串");
        //string strs = Console.ReadLine();
        //char[] chs = new char[strs.Length];
        //int i = 0;
        //foreach (var item in strs)
        //{
        //    chs[i] = item;
        //    i++;
        //}
        //foreach (var item in chs)
        //{
        //    Console.WriteLine(item);
        //}
        //Console.ReadKey();

        //统计Welcome to china 中每个字符出现的次数,不考虑大小写
        string str = "Welcome to china";
        Dictionary<char, int> dic = new Dictionary<char, int>();
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == ‘ ‘)
            {
                continue;
            }
            //如果dic已经包含了当前循环到的这个键
            if (dic.ContainsKey(str[i]))
            {
                //值再次加1
                dic[str[i]]++;
            }
            //字符在集合中第一次出现
            else
            {
                dic[str[i]] = 1;
            }
        }
        foreach (KeyValuePair<char,int> kv in dic)
        {
            Console.WriteLine("字母{0}出现了{1}次", kv.Key, kv.Value);
        }
        Console.ReadKey();
    }

四、FileStream方法(对文件操作)
FileStream(一点一点读取,对内存压力小) 操作字节
StreamReader和StreamWriter 操作字符

将创建文件流对象的过程写在using当中,会自动帮助我们释放流所占用的资源

static void Main(string[] args)
    {
        ////使用FileStream来读取数据
        ////1.创建一个FileStream类   所需三个参数:路径、针对这个文件做什么操作、针对这个文件里面的数据做什么操作
        //FileStream fs = new FileStream(@"C:\Users\Administrator\Desktop\1.txt",FileMode.OpenOrCreate,FileAccess.Read);
        //byte[] buffer = new byte[1024 * 1024 * 5];
        ////返回本次实际读取到的有效字节数
        //int r = fs.Read(buffer,0,buffer.Length);
        ////将字节数组中每一个元素按照指定的编码格式解码成字符串,从0开始到r结束
        //string s = Encoding.Default.GetString(buffer,0,r);
        ////关闭流
        //fs.Close();
        ////释放流所占用的资源
        //fs.Dispose();
        //Console.WriteLine(s);
        //Console.ReadKey();

        //使用FileStream写入数据
        using (FileStream fsWrite = new FileStream(@"C:\Users\Administrator\Desktop\1.txt",FileMode.OpenOrCreate,FileAccess.Write))
        {
            string str = "看我何平何胖子把你覆盖";
            byte[] buffer = Encoding.Default.GetBytes(str);
            fsWrite.Write(buffer,0,buffer.Length);
        }
        Console.WriteLine("写入OK");
        Console.ReadKey();
    }

FileStream实现多媒体文件的复制

static void Main(string[] args)
    {
        //思路:先将要复制的多媒体文件读取出来,然后写入到指定的位置
        string source = @"D:\BaiduNetdiskDownload\(第十二天)\video\1、复习.avi";
        string target = @"C:\Users\Administrator\Desktop\new.avi";
        CopyFile(source, target);
        Console.WriteLine("复制成功");
        Console.ReadKey();
    }

    public static void CopyFile(string source, string target)
    {
        //1.创建一个负责读取的流
        using (FileStream fsRead = new FileStream(source, FileMode.Open, FileAccess.Read)) 
        {
            //2.创建一个负责写入的流
            using (FileStream fsWrite = new FileStream(target, FileMode.OpenOrCreate, FileAccess.Write)) 
            {
                byte[] buffer = new byte[1024 * 1024 * 5];
                //4.因为文件可能会比较大,所以在读取的时候,应该通过循环去读取
                while (true)
                {
                    //3.返回本次读取实际读取到的数据字节数
                    int r = fsRead.Read(buffer, 0, buffer.Length);
                    //5.如果返回一个0,也就意味着什么都读取不到,读取完了
                    if (r == 0)
                    {
                        break;
                    }
                    fsWrite.Write(buffer, 0, r);
                }
            }
        }
    }

五、StreamReader和StreamWrite
语法及用法:

static void Main(string[] args)
    {
        ////使用StreamReader来读取一个文本文件
        //using (StreamReader sr = new StreamReader(@"C:\Users\Administrator\Desktop\1.txt"))
        //{
        //    while (!sr.EndOfStream)
        //    {
        //        Console.WriteLine(sr.ReadLine());
        //    }
        //}

        ////使用StreamWrite来写入一个文本文件
        //using (StreamWriter sw = new StreamWriter(@"C:\Users\Administrator\Desktop\1.txt"))
        //{
        //    sw.Write("今天天气不错,挺风和日丽的"); //写入后覆盖掉原内容
        //}
        //Console.WriteLine("写入成功");

        //使用StreamWrite来写入一个文本文件,不覆盖
        using (StreamWriter sw = new StreamWriter(@"C:\Users\Administrator\Desktop\1.txt",true))
        {
            sw.Write("今天天气不错,挺风和日丽的"); //写入后覆盖掉原内容
        }
        Console.WriteLine("写入成功");
        Console.ReadKey();
    }

六、多态
概念:让一个对象能够表现出多种状态(类型)
实现多态的三种方法:1.虚方法 2.抽象类 3.接口
1、虚方法 (减少代码量并且增加了程序的可扩展性)
步骤
1.将父类的方法标记为虚方法,使用关键字virtual,这个函数可以被子类重新写一遍
2.在子类方法前标记,使用关键字override

语法及作用示范

namespace _06多态
{
class Program
{
    static void Main(string[] args)
    {
        //概念:让一个对象能够表现出多种的状态(类型)
        //

        Chinese cn1 = new Chinese("韩梅梅");
        Chinese cn2 = new Chinese("李雷");
        Japanese j1 = new Japanese("不穿裤子");
        Japanese j2 = new Japanese("没穿内衣");
        Korea k1 = new Korea("金吃屎");
        Korea k2 = new Korea("宋吃翔");
        America a1 = new America("蝙蝠侠");
        America a2 = new America("蜘蛛侠");
        Person[] pers = { cn1, cn2, j1, j2, k1, k2, a1, a2 };
        for (int i = 0; i < pers.Length; i++)
        {
            ////这一坨代码,就是干一件事,分别打招呼,如果最后那一行能实现这一坨代码,减少N多代码量
            ////并且在加入新类时候,只需要写类,不需要在来这里判断
            //if (pers[i] is Chinese)
            //{
            //    ((Chinese)pers[i]).SayHello();
            //}
            //else if (pers[i] is Japanese)
            //{
            //    ((Japanese)pers[i]).SayHello();
            //}
            //else if (pers[i] is Korea)
            //{
            //    ((Korea)pers[i]).SayHello();
            //}
            //else
            //{
            //    ((America)pers[i]).SayHello();
            //}
            pers[i].SayHello();//这样一行代码就搞定,并且加入新类也能使用
        }
        Console.ReadKey();
    }
}

public class Person
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public Person(string name)
    {
        this.Name = name;
    }
    public virtual void SayHello()
    {
        Console.WriteLine("我是人类");
    }
}

public class Chinese : Person
{
    public Chinese(string name) : base(name)
    { }
    public override void SayHello()
    {
        Console.WriteLine("我是中国人,我叫{0}", this.Name);
    }
}

public class Japanese : Person
{
    public Japanese(string name) : base(name)
    { }
    public override void SayHello()
    {
        Console.WriteLine("我是日本人,我叫{0}", this.Name);
    }
}

public class Korea : Person
{
    public Korea(string name) : base(name)
    { }
    public override void SayHello()
    {
        Console.WriteLine("我是棒子国人,我叫{0}", this.Name);
    }
}

public class America : Person
{
    public America(string name) : base(name)
    { }
    public override void SayHello()
    {
        Console.WriteLine("我是漂亮国人,我叫{0}", this.Name);
    }
}

}

虚方法的练习

 namespace _07虚方法的练习
{
class Program
{
    static void Main(string[] args)
    {
        //真的鸭子嘎嘎叫 木头鸭子吱吱叫 橡皮鸭子唧唧叫
        Duck rd = new Duck();
        MuDuck md = new MuDuck();
        XPDuck xd = new XPDuck();
        Duck[] ducks = { rd, md, xd };
        for (int i = 0; i < ducks.Length; i++)
        {
            ducks[i].back();
        }
        Console.ReadKey();
    }
}

public class Duck
{
    public virtual void back()
    {
        Console.WriteLine("真的鸭子嘎嘎叫");
    }
}

public class MuDuck : Duck
{
    public override void back()
    {
        Console.WriteLine("木头鸭子吱吱叫");
    }
}

public class XPDuck : Duck
{
    public override void back()
    {
        Console.WriteLine("橡皮鸭子唧唧叫");
    }
}
  }

虚方法的练习二

 namespace _07虚方法的练习
{
class Program
{
    static void Main(string[] args)
    {
        //经理十一点打卡,员工九点打卡,程序员不打卡
        Employee emp = new Employee();
        Manager mg = new Manager();
        Programmer pm = new Programmer();
        Employee[] emps = { emp, mg, pm };
        for (int i = 0; i < emps.Length; i++)
        {
            emps[i].Daka();
        }
        Console.ReadKey();
    }
}
public class Employee
{
    public virtual void Daka()
    {
        Console.WriteLine("员工九点打卡");
    }
}

public class Manager : Employee
{
    public override void Daka()
    {
        Console.WriteLine("经理十一点打卡");
    }
}

public class Programmer : Employee
{
    public override void Daka()
    {
        Console.WriteLine("程序员不打卡");
    }
}
}

七、抽象类
1.当父类中的方法不知道如何实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法
2.抽象类使用关键字:abstract 加到抽象类和抽象方法上。抽象方法是没有方法体的。
3.抽象成员必须在抽象类中
4.抽象类不能被实例化
5.子类继承抽象类后,必须把父类中的所有抽象成员都重写
(除非子类也是一个抽象类,则可以不重写)
6.在抽象类中可以包含实例成员,并且抽象类的实例成员可以不被子类实现
7.抽象类是有构造函数的,虽然不能被实例化
8.如果父类的抽象方法中有参数,继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。如果抽象父类的抽象方法中有返回值,子类在重写这个抽象方法的时候,也必须要传入返回值
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现
如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。

语法及用途:

namespace _08抽象类
{
class Program
{
    static void Main(string[] args)
    {
        //狗会叫 猫也会叫
        Animal a = new Dog();
        a.Brak();
        Animal b = new Cat();
        b.Brak();
        Console.ReadKey();
    }
}

public abstract class Animal
{
    public abstract void Brak();
}

public class Dog : Animal
{
    public override void Brak()
    {
        //throw new NotImplementedException();
        Console.WriteLine("狗旺旺旺的叫");
    }
}

public class Cat : Animal
{
    public override void Brak()
    {
        //throw new NotImplementedException();
        Console.WriteLine("猫喵瞄喵的叫");
    }
}
}

抽象类的练习(求圆和矩形的面积及周长)

namespace _09抽象类的练习
{
class Program
{
    static void Main(string[] args)
    {
        //使用多台求矩形的面积和周长以及圆形的面积和周长
        Shape shape = new Square(5, 6); //new Circle(5);
        double area = shape.GetArea();
        double perimeter = shape.GetPerimeter();
        Console.WriteLine("这个形状的面积是{0},周长是{1}", area, perimeter);
        Console.ReadKey();
    }
}
/// <summary>
/// 抽象出一个类来作为父类
/// </summary>
public abstract class Shape
{
    public abstract double GetArea();
    public abstract double GetPerimeter();
}
/// <summary>
/// 求圆的面积和周长
/// </summary>
public class Circle : Shape
{
    private double _r;
    public double R
    {
        get { return _r; }
        set { _r = value; }
    }

    public Circle(double r)
    {
        this.R = r;
    }

    public override double GetArea()
    {
        return Math.PI * this.R * this.R;
    }

    public override double GetPerimeter()
    {
        return 2 * Math.PI * this.R;
    }
}

/// <summary>
/// 求矩形的面积和周长
/// </summary>
public class Square : Shape
{
    private double _height;
    public double Height
    {
        get { return _height; }
        set { _height = value; }
    }
    private double _width;
    public double Width
    {
        get { return _width; }
        set { _width = value; }
    }
    public Square(double height, double width)
    {
        this.Height = height;
        this.Width = width;
    }
    public override double GetArea()
    {
        return this.Height * this.Width;
    }

    public override double GetPerimeter()
    {
        return (this.Height + this.Width) * 2;
    }
}
}

九、模拟移动硬盘,U盘,MP3插入电脑进行读取操作的练习

namespace _10使用多态模拟U盘_移动硬盘_MP3插入电脑读写数据
{
class Program
{
    static void Main(string[] args)
    {
        //MobileDisk md = new MobileDisk();
        //UDisk ud = new UDisk();
        //MP3 mp3 = new MP3();
        //Computer cpu = new Computer();
        //cpu.CpuRead(ud);
        //cpu.CpuWrite(ud);

        //MobileStorage ms = new UDisk();
        //Computer cpu = new Computer();
        //cpu.CpuRead(ms);
        //cpu.CpuWrite(ms);

        MobileStorage ms = new UDisk();
        Computer cpu = new Computer();
        cpu.Ms = ms;
        cpu.CpuRead();
        cpu.CpuWrite();
        Console.ReadKey();

    }
}

/// <summary>
/// 新建一个父类来存储子类的公有方法读和写
/// </summary>
public abstract class MobileStorage
{
    public abstract void Read();
    public abstract void Write();
}

/// <summary>
/// 创建移动硬盘类,来模拟移动硬盘的操作
/// </summary>
public class MobileDisk : MobileStorage
{
    public override void Read()
    {
        Console.WriteLine("移动硬盘在读取数据");
    }

    public override void Write()
    {
        Console.WriteLine("移动硬盘在写入数据");
    }
}

/// <summary>
/// 创建U盘类,模拟U盘的操作
/// </summary>
public class UDisk : MobileStorage
{
    public override void Read()
    {
        Console.WriteLine("U盘在读取数据");
    }

    public override void Write()
    {
        Console.WriteLine("U盘在写入数据");
    }
}

/// <summary>
/// 创建MP3类,模拟MP3的操作
/// </summary>
public class MP3 : MobileStorage
{
    public override void Read()
    {
        Console.WriteLine("MP3在读取数据");
    }

    public override void Write()
    {
        Console.WriteLine("MP3在写入数据");
    }

    public void PlayMusic()
    {
        Console.WriteLine("MP3自己可以播放音乐");
    }
}

/// <summary>
/// 创建电脑类,调用移动存储类的读写两个方法,传入参数实际是被子类从新赋值后的
/// </summary>
public class Computer
{
    private MobileStorage _ms;
    public MobileStorage Ms
    {
        get { return _ms; }
        set { _ms = value; }
    }
    // public void CpuRead(MobileStorage ms)
    public void CpuRead()//直接使用字段赋值
    {
        Ms.Read();
    }
    // public void CpuWrite(MobileStorage ms)
    public void CpuWrite()//直接使用字段赋值
    {
        Ms.Write();
    }
}
} 

C#基础入门第十二天(面向对象多态,File操作流,泛型集合)

上一篇:c#软件如何统计在线人数


下一篇:C#将DataTable按固定个数拆分成多个表