C#

学C#的第13天

森岩
2022-07-30 / 0 评论 / 2 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年08月18日,已超过1206天没有更新,若内容或图片失效,请留言反馈。

1、C#中的访问修饰符

1.类型

  1. public:公共的公开的
  2. private:私有的,只能在当前类的内部访问
  3. protected:受保护的,只能在当前类的内部以及该类的子类中访问
  4. internal:只能在当前程序集(项目)中访问。在同一项目中,internal和public的权限是一样的
  5. protected internal:同项目中,internal的权限要大于protected,但是一旦跨项目就不一定了。

2. 注意:

  1. 能修饰类的只有public和internal
  2. 可访问性不一致:子类的访问权限不能高于父类的访问权限。如果internal类的子类被其他项目引用,就出现了不能访问internal类但是可以通过子类访问internal类中的protected成员的情况。此时就暴露了父类成员,与给父类写成internal的原因就是不想让其他项目访问到的想法相悖。

2、添加同一解决方案中项目的引用

  右击引用的项目栏下的引用--->添加引用--->项目--->选择想要被引用的项目--->在命名空间上面添加引用

3、简单工厂设计模式

  1. 解决问题:当我有多个方法可能被用户调用,在用户调用之前我不知道需要给用户哪一个
  2. 实现功能:当用户调用的时候,返回一个父类,在父类中调用用户需要的子类
  3. 举例:
internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入你需要的笔记本品牌");
            string brand = Console.ReadLine();
            NoteBook nb = GetNoteBook(brand);
            nb.SayHello();
            Console.ReadKey();
        }
        /// <summary>
        /// 简单工厂的核心:根据用户的输入创建对象赋值给父类
        /// </summary>
        /// <param name="brand"></param>
        /// <returns></returns>
        public static NoteBook GetNoteBook(string brand)
        {
            NoteBook nb = null;
            switch (brand)
            {
                case "联想":
                    nb = new Lenovo();
                    break;
                case "宏碁":
                    nb = new Acer();
                    break;
                case "戴尔":
                    nb = new Dell();
                    break;
                case "IBM":
                    nb = new IBM();
                    break;
            }
            return nb;
        }
    }
    public abstract class NoteBook
    {
        public abstract void SayHello();
    }
    public class Lenovo : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是联想笔记本");
        }
    }
    public class Acer : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是宏碁笔记本");
        }
    }
    public class Dell : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是戴尔笔记本");
        }
    }
    public class IBM : NoteBook
    {
        public override void SayHello()
        {
            Console.WriteLine("我是IBM笔记本");
        }
    }

3、值传递和引用传递

  1. 值类型在复制的时候,传递的是这个值的本身
  2. 引用类型在复制的时候,传递的是对这个对象的引用。也就是说,二者在堆中存的是同一个地址,这个地址对应着栈中相同位置。当改变二者之一的时候,改变的是栈中的内容,这事无论调用二者哪一个,都是已经改变的内容。 但是 ,由于字符串的不可变性,因此每次复制字符串的时候都是开辟一块新的空间
  3. ref:当在方法中使用ref的时候,可以做到里面的值跟着外面的改变。其实现的方法是:在复制的时候,直接把外部变量在栈中的地址而不是值赋值给内部变量,这样就做到了两个变量都指向一个地址,从而实现功能。

4、序列化和反序列化

1. 概念

  1. 序列化:将对象转换为二进制
  2. 反序列化:将二进制转换为对象

2. 作用:

  传输数据。在不同电脑之间传输文件的时候都是使用二进制,因此如果我想要把文件传到别人电脑上,需要先序列化,然后传输过去,别人再反序列化。

3. 序列化步骤

  1. 将对象标记为序列化。在类的上一行标记[Serializable],只有被标记的类创建的对象才能序列化
  2. 使用流将对象序列化到一个位置,举例:
    internal class Program
    {
        static void Main(string[] args)
        {
            //初始化对象
            Person p = new Person();
            p.Name = "张三";
            p.Gender = '男';
            p.Age = 19;
            //将对象以序列化形式存入桌面
            using (FileStream fsWrite = new FileStream(@"C:\Users\crg88\Desktop\111.txt", FileMode.OpenOrCreate, FileAccess.Write))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(fsWrite, p);//无需再写.Write,因为这个方法里面就包含了
            }
            Console.WriteLine("转换完成");
            Console.ReadKey();
        }
    }
    [Serializable]
    public class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private char _gender;
        public char Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }
        private int _age;
        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
    }

4. 反序列化步骤

  1. 举例:
            Person p;
            using (FileStream fsRead=new FileStream(@"C:\Users\crg88\Desktop\111.txt", FileMode.OpenOrCreate, FileAccess.Read))
            {
                BinaryFormatter bf = new BinaryFormatter();
                p = (Person)bf.Deserialize(fsRead);
            }

5、partial部分类

  1. 作用:在项目开发时,有时候多个人可能会写好多个同名类,这时候就会造成冲突。
  2. 用法:在类的访问修饰符后面加一个partial
  3. 解释:使用部分类,相当于是把一个类分成了几部分,他们是互通的,可以把所有同名部分类看作一个类。因此两个同名的部分类分别写的成员可以互相用,同名的方法不能出现多次。

6、sealed密封类

  1. 作用:不想让自己的类被继承
  2. 用法:在类的访问修饰符后面加一个sealed
  3. 特点:不能被继承,可以继承其他类

7、ToString()是Object类的虚方法,子类可以重写。

8、interface接口(实现多态的第三种手段)

1. 作用

  1. 有时候,一个子类想继承多个父类,但是由于继承的单根性,不能实现。接口便是解决这个问题
  2. 不同类有同一个元素的时候使用

2. 解释

  1. 接口就是一个规范、能力
  2. 不同事物拥有同一种能力,这时候由于是不同事物,没办法写成父类,这时候就用到接口

3. 语法

[public] interface I..able
{
    成员;
}

 英语中以i开头,以e结尾一般表示一种能力

4.特点:

  1. 一个子类继承一个接口,必须实现这个接口的成员
  2. 接口中的成员不允许添加访问修饰符,默认就是public。
  3. 只能写没有方法体的方法:方法、自动属性、索引器、事件。不允许写字段和构造函数。
  4. 接口中的成员不能有任何实现,让子类去做
  5. 不能实例化:静态类、抽象类、接口。因为接口里的方法没有实现。
  6. 接口与接口之间可以继承,没有单根性
  7. 接口不能继承一个类,而类可以继承接口(接口只能继承于接口,而类既可以继承接口,也可以继承类)
  8. 一个类如果既继承了接口,又继承了类,那么在语法上必须先写类,再写接口

5. 显式实现接口

  1. 作用:解决方法重名的问题。假如原类就有一个方法,继承的接口里面也有一个同名的方法,则自动认为接口里的方法已经被实现,因此需要显式实现。
  2. 举例:
    public class Bird : IFlyable
    {
        public void Fly()
        {
            Console.WriteLine("鸟会飞");
        }
        void IFlyable.Fly()
        {
            Console.WriteLine("我是接口的飞");
        }
    }
    interface IFlyable
    {
        void Fly();
    }

9、自动属性

  1. 举例:
        public int Age
        {
            get;
            set;
        }
  1. 虽然没有写字段,但是在生成的时候会自动生成一个字段
  2. 由于没有方法体,所以不能在get和set里面对读入数据进行处理,只能用构造函数的方法进行处理

10、Guid

  1. 作用:产生一个不会重复的编号
  2. Guid.NewGuid()返回一个Guid类型的编号,在使用时通常.ToString()
0

评论

博主关闭了所有页面的评论