面向对象---继承

一、命名空间:可以看作是类的文件夹,用来解决类的重名问题。

1、导入命名空间

1)、Alt+Shift+F10(快捷键);

2)、鼠标放在类名字上,最左面会出现一个小箭头,点击显示可修补程序,然后导入需要的命名空间。

2、引用其他项目的类

1)、添加引用;

2)引用命名空间。

二、值类型和引用类型(变量类型):两者传递值的方式不一样,值类型称为值传递,引用类型称为引用传递。

1、值类型

1)各个值类型:int, double, bool, char, decimal, struct, enum, 可空类型。

2)存储位置:值类型的值存储在内存的栈中

2、引用类型

1)、各个引用类型:string, 类,接口,委托,数组,object。

2)存储位置:引用类型的值存储在内存的堆中。同时,引用类型同样会在栈中开辟空间,存放引用(堆中的值的地址)。

3、两种类型的存储位置分析图

三、字符串的特性

1、字符串的不可变性:当给字符串重新赋值时,原来的值并不会改变,而是开辟新的内存空间存储新值。当程序结束后,GC扫描整个内存时,如果发现有的内存空间没有被指向,则立刻销毁它。

2、字符串可以看作是一个char类型的只读数组,我们可以通过下标去访问字符串中的某个元素。

如果你想改变其中某个元素的值,可以
1)先将字符串转化为char类型的数组
2)将字符数组转化为字符串

 string s = "abc";
Console.WriteLine(s[0]);//返回char类型元素
char[] chs = s.ToCharArray();
chs[0] = 'b';
 s = new string(chs);

四、继承:把几个类中重复的成员单独拿出来封装成一个类,做为这几个类的父类,然后子类可以继承父类的属性和方法(成员)。用来解决代码冗余问题。

1、父类---》基类,子类---》派生类

2、继承的特性

1)单根性:一个子类只能有一个父类;

2)传递性:派生类从基类中继承特性,同时派生类也可以成为其他类的基类。这样就从一个基类派生出多层类,形成类层次结构。

3、object类是所有类的基类。所有类都直接或间接地继承了object类。

4、注意事项:

1)子类无法访问父类的私有字段;

2)子类没有继承到父类的构造函数。当创建子类对象时,子类会先调用父类默认的无参数构造函数来创建父类对象,让子类可以使用父类中的成员,然后再调用子类的构造函数创建子类对象。

3)如果父类默认无参的构造函数被新写的构造函数覆盖掉,子类调用不到会报错。我们可以用一下解决方法:

a、在父类中重新写一个无参的构造函数;

b、在子类显示调用父类的构造函数,使用关键字base。

namespace Inheritance
{
    public class person
    {
        public string Name {get; set; }
        public int Age { get; set; }
        public person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }

    public class student:person
    {
        public student(string name, int age) : base(name, age)
        {
            Console.WriteLine("我叫{0},今年{1}岁",name ,age);
        }
        static void Main(string[] args)
        {
            student s = new student("张三", 18);
            Console.ReadKey();
        }
    }
}

五、里氏转换

1、子类可以赋值给父类。如果有一个地方需要父类作为参数,可以传递一个子类对象进去。

2、如果父类中装的是子类对象,那么这个父类是强制转为子类对象。

3、as运算符和is运算符

1)、as运算符用于兼容的引用类型之间执行类型转换,转换成功返回相应的对象,否则返回false。

2)、is运算符用来检查对象是否跟给定的类型兼容并执行类型转换,转换成功返回true,否则返回false。

例子:

namespace 里氏转换
{
    class Program
    {
        static void Main(string[] args)
        {
            person p = new student();//把子类对象传递给父类
            if (p is student)//使用is进行类型转换,把父类强制转换成子类对象
            {
                ((student)p).StudentSayHi();
            }
            student s2 = p as student;//使用as进行类型转换,把父类强制转换成子类对象
            s2.StudentSayHi();

            Console.ReadKey();
        }
    }

    class person
    {
        public void SayHi()
        {
            Console.WriteLine("我是人类。");
        }
    }

    class student : person
    {
        public void StudentSayHi()
        {
            Console.WriteLine("我是学生。");
        }
    }
}

在控制台换行打印出:

我是学生。

我是学生。

 

六、集合:很多数据的一个集合,长度可以任意改变,类型不限。(在命名空间System.Collections中)

1、ArrayList集合

例子:

 

namespace Collection
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个集合对象
            ArrayList list = new ArrayList();
            list.Clear();//移除所有元素
            list.Add(1); //添加单个元素
            list.Add(2);
            list.Add(3);
            list.Add("多余的");
            list.Add('c');
            list.Add("hello");
            list.Add(true);
            list.AddRange(new int[] { 1, 2, 3, 4}); //添加集合元素
            Rose r = new Rose();
            list.Add(r);//添加子类对象
            //list.AddRange(list);//可以添加集合本身
            list.Insert(1, "插入的");//在指定位置中插入单个元素
            list.InsertRange(0, new int[] { 1, 2, 3 });//在指定位置插入集合
            list.Reverse(); //反转集合的元素
            list.Remove("多余的");//写谁就删除谁
            list.RemoveAt(0);//根据下标删除元素,删除第一个元素1
            list.RemoveRange(0,2);//根据索引删除一定范围的元素,删除第一个到第三个元素
            //list.Sort();//升序排列
            bool b = list.Contains(1);//判断是否包含元素1,返回布尔类型
            for (int i = 0; i < list.Count; i++)//Count---》获取当前集合个数
            {
                //里氏转换
                if (list[i] is Rose)
                {
                    ((Rose)list[i]).roseSayHi();
                 }
                Console.WriteLine(list[i]);
            }
            Console.WriteLine(b);

            Console.ReadKey();
        }
    }
    class Rose
    {
        public void roseSayHi()
        {
            Console.WriteLine("I'm a Rose~");
        }
    }
}

2、Hastable 键值对集合 

1)键必须是唯一的,而值可以重复。

2)、在键值对集合中,根据键去找值

3)用foreach来遍历键值对集合中所有的元素。在访问大数据时,foreach的效率要高于for循环。

例子:

namespace HasTable1
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个新的键值对集合对象
            Hashtable ht = new Hashtable();
            ht.Add(1, "hello"); //添加新数据  键和键值可以为任何数据类型
            ht.Add(false,"world");
            ht.Add(2,'!');
            ht[3] = "hi,chaara"; //另一种添加数据的方法。如果不存在该键,则添加新数据,如果存在该键,则用新数据覆盖以前的数据

            //判断是否存在该键,没有则添加该键以及键值,有的话则提示已经存在该键
            if (!ht.ContainsKey(4))
            {
                ht.Add(4, "bye~");
            }
            else
            {
                Console.WriteLine("已存在该键!");
            }

            //用foreach遍历该集合的键,并且打印出键跟键值
            foreach (var item in ht.Keys)
            {
                Console.WriteLine("键是:{0}========键值是:{1}",item, ht[item]);
            }
            Console.ReadKey();
        }
    }
}

3、List泛型集合

1)、元素类型随集合类型的确定而确定下来。

2)List泛型集合和数组可以互相转换。

例子:

    class Program
    {
        static void Main(string[] args)
        {
            //创建一个泛型集合对象  
            List<int> list = new List<int>();
            list.Add(1);//添加单个元素
            list.Add(2);
            list.AddRange(new int[] { 3, 4, 5 }); //添加集合
            list.AddRange(list);
            //List泛型集合可以转换为数组
            int[] nums = list.ToArray();
            //数组可以转换为泛型集合
            List<int> list2 = nums.ToList();
            for (int i = 0; i < list2.Count; i++)
            {
                Console.WriteLine(list2[i]);  //list[i] 指定索引处
            }

            Console.ReadKey();
        }
    }

4、Dictionary 字典:键和值的类型要确定

例子:

    class Program
    {
        static void Main(string[] args)
        {
            //Dictionary 泛型字典集合 值和键类型确定
            Dictionary<int, string> dic = new Dictionary<int, string>();
            dic.Add(1,"吟诗");
            dic.Add(2,"花粥");//键必须是唯一的
            dic[1] = "诗听";//添加键跟值,如果键已存在,则覆盖原来的值
            //根据键来遍历
            foreach (var item in dic.Keys)
            {
                Console.WriteLine("{0}----->{1}",item, dic[item]);
            }
            //根据键值对遍历,kv代表键和键值这个整体
            foreach (KeyValuePair<int, string> kv in dic)
            {
                Console.WriteLine("{0}----->{1}",kv.Key, kv.Value);
            }
            Console.ReadKey();
        }
    }

5、集合长度问题

1、count和capity

1)count:表示这个集合中实际包含的元素个数。

2)capity:表示这个集合中可以包含的元素。

2、每次集合中实际包含的元素个数(count)超过了可以包含的元素个数时(capity)时,集合就会向内存多申请开辟多一倍的空间,来保证集合的长度够用。这也就是为什么集合的长度可以不定的原因。

 

七、Path类:操作文件路径(在命名空间System.IO下)

例子:

    class Program
    {
        static void Main(string[] args)
        {
            string str = @"C:\Users\D\Desktop\test.txt";
            Path.GetFileName(str); //获得该路径下的文件名
            Path.GetFileNameWithoutExtension(str);//获得该路径下没有扩展名的文件名
            Path.GetExtension(str);//获得该路径下文件的扩展名
            Path.GetDirectoryName(str);//获得该路径下文件所在的文件夹名称
            Path.GetFullPath(str);//获得文件所在的全路径
            Path.Combine(@"c:\", "b.txt");//连接两个字符串作为路径

        }
    }

八、File类:操作任意类型的文件。只能操作一些小文件。(在命名空间System.IO下)

1、一般用法

            File.Create(@"C:\Users\\Desktop\chaara.txt"); //创建一个新文件
            Console.WriteLine("创建完成!");
            Console.ReadKey();
            //File.Create(@"C:\Users\DuffyH\Desktop\chara.txt");
            File.Delete(@"C:\Users\D\Desktop\chara.txt"); //删除一个文件
            Console.WriteLine("删除完成!");
            Console.ReadKey();
            File.Copy(@"C:\Users\D\Desktop\chaara.txt", @"C:\Users\DuffyH\Desktop\chaara2.txt"); //复制一个文件到新文件
            Console.WriteLine("复制完成!");
            Console.ReadKey();
            File.Move(@"C:\Users\D\Desktop\chaara.txt", @"C:\chaara.txt"); //只能在同一个逻辑盘下进行文件转移
            Console.WriteLine("移动完成!");
            Console.ReadKey();

2、ReadAllBytes:以字节为单位读取文件

            //将文件的内容读入一个字符串,将字节数组中的每一个元素都按照指定的编码格式解码成字符串
            string path = @"C:\Users\D\Desktop\test.txt";
            byte[] b = File.ReadAllBytes(path);
            string s = Encoding.Default.GetString(b);
            Console.WriteLine(s);
            Console.ReadKey();

3、ReadAllLines:以行的方式读取文件

            string path = @"C:\Users\D\Desktop\chaara.txt";
            string[] contents = File.ReadAllLines(path, Encoding.Default);
            foreach (string item in contents)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();

4、ReadAllText:读取整个文本文件

            string path = @"C:\Users\D\Desktop\chaara.txt";
            string str = File.ReadAllText(path, Encoding.Default);
            Console.WriteLine(str);
            Console.ReadKey();

5、WriteAllLines :以行的方式写入文件

            string path = @"C:\Users\D\Desktop\test.txt";
            File.WriteAllLines(path, new string[] { "这是一个充实的下午。", "外面的阳光很好~" });
            Console.WriteLine("OK!");

6、WriteAllText:创建一个新文件,在其中写入指定的字符串;如果目标文件已存在,则覆盖该文件

            string path = @"C:\Users\D\Desktop\test.txt";
            File.WriteAllText(path, "山中何事,松花酿酒,春水煎茶。");

7、AppendAllText:对目标文件进行追加写入,不覆盖源文件

            string path = @"C:\Users\D\Desktop\test.txt";
            File.AppendAllText(path, "这是新内容");

 

九、装箱和拆箱

1、装箱:将值类型转换成引用类型。

2、拆箱:将引用类型转换成值类型。

3、判断方法:两种类型存在继承关系,才会发生了装箱或者拆箱。

例子:

int n = 10;
object o = n;//装箱
int n2=(int)o;//拆箱

string str = "123";
int n = Convert.ToInt32(str);//这里并没有进行拆箱

4、我们应该尽量避免装箱和拆箱,因为这是较为影响性能的操作。

 

十、FileStream文件流:文件流是操作字节的,所以用它可以操作任意类型的文件。用来操作大文件,因为它是一点点地读取文件,可以减少对内存压力。(在命名空间System.IO下)

1、使用FileStream读取文件

            string path = @"C:\Users\D\Desktop\文件流.txt";
            //创建一个文件流对象,参数1是文件的路径,参数2是操作文件,参数3是操作文件中的数据
            FileStream fsRead = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
            byte[] buffer = new byte[1024 * 1024 * 5];
            //参数1为每次读取数据的量,参数2为开始读取数据的位置,参数3为每次最多读取数据的量
            int read = fsRead.Read(buffer, 0, buffer.Length);
            //将字节数组中每一个元素按照指定的编码格式解码成字符串
            string s = Encoding.Default.GetString(buffer, 0, read);//参数3表示,虽然读取了5M,但只解码了文件实际的字节

            //关闭流
            fsRead.Close();
            //释放流占用的内存 GC并不会自动释放流占用的空间
            fsRead.Dispose();
            Console.WriteLine(s);

2、使用FileStream写入数据(将创建文件流对象的过程写在using中,文件流所占用的资源会自动释放)

            string path = @"C:\Users\D\Desktop\文件流.txt";
            using (FileStream fsWrite = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))//创建一个文件流对象
            {
                string str = "新内容";
                byte[] buffer = Encoding.Default.GetBytes(str);
                fsWrite.Write(buffer, 0, buffer.Length);
            }
            Console.WriteLine("写入成功!");

练习:使用文件流来实现多媒体文件的复制

    class Program
    {

        static void Main(string[] args)
        {

            //使用文件流来实现多媒体文件的复制
            string source = @"E:\BaiduNetdiskDownload\08使用FileStream实现多媒体文件的复制.avi";
            string target = @"C:\Users\DDesktop\new.avi";
            CopyFile(source, target);

            Console.WriteLine("复制成功!");
            Console.ReadKey();

        }

        //使用文件流来实现多媒体文件的复制
        public static void CopyFile(string source, string target)
        {
            using (FileStream fsRead = new FileStream(source, FileMode.Open, FileAccess.Read))
            {
                using (FileStream fsWrite = new FileStream(target, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    byte[] buffer = new byte[1024 * 1024 * 5];
                    while (true)
                    {
                        int read = fsRead.Read(buffer, 0, buffer.Length);
                        if (read == 0)
                        {
                            break;
                        }
                        fsWrite.Write(buffer, 0, buffer.Length);
                    }
                }
            }
        }

十一、stream:(在命名空间System.IO下)

1、StreamReader:以行的形式来读取一个文本文件数据

            using (StreamReader sr = new StreamReader(@"C: \Users\D\Desktop\文件流.txt", Encoding.Default))
            {
                //通过循环读取所有行
                while (!sr.EndOfStream)
                {
                    Console.WriteLine(sr.ReadLine());
                }
            }

2、StreamWriter:以行的形式来把数据写入一个文本文件

            using (StreamWriter sw = new StreamWriter(@"C: \Users\D\Desktop\文件流1.txt", true))
            {//当参数2为true时,不覆盖文本原有数据,为false则覆盖
                sw.WriteLine("追着我就跑!");
                Console.WriteLine("写入成功!");
            }

 

posted @ 2017-08-18 19:39  张晨子  阅读(307)  评论(0编辑  收藏  举报