1、C#中的访问修饰符
1.类型
- public:公共的公开的
- private:私有的,只能在当前类的内部访问
- protected:受保护的,只能在当前类的内部以及该类的子类中访问
- internal:只能在当前程序集(项目)中访问。在同一项目中,internal和public的权限是一样的
- protected internal:同项目中,internal的权限要大于protected,但是一旦跨项目就不一定了。
2. 注意:
- 能修饰类的只有public和internal
- 可访问性不一致:子类的访问权限不能高于父类的访问权限。如果internal类的子类被其他项目引用,就出现了不能访问internal类但是可以通过子类访问internal类中的protected成员的情况。此时就暴露了父类成员,与给父类写成internal的原因就是不想让其他项目访问到的想法相悖。
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、值传递和引用传递
- 值类型在复制的时候,传递的是这个值的本身
- 引用类型在复制的时候,传递的是对这个对象的引用。也就是说,二者在堆中存的是同一个地址,这个地址对应着栈中相同位置。当改变二者之一的时候,改变的是栈中的内容,这事无论调用二者哪一个,都是已经改变的内容。 但是 ,由于字符串的不可变性,因此每次复制字符串的时候都是开辟一块新的空间
- ref:当在方法中使用ref的时候,可以做到里面的值跟着外面的改变。其实现的方法是:在复制的时候,直接把外部变量在栈中的地址而不是值赋值给内部变量,这样就做到了两个变量都指向一个地址,从而实现功能。
4、序列化和反序列化
1. 概念
- 序列化:将对象转换为二进制
- 反序列化:将二进制转换为对象
2. 作用:
传输数据。在不同电脑之间传输文件的时候都是使用二进制,因此如果我想要把文件传到别人电脑上,需要先序列化,然后传输过去,别人再反序列化。
3. 序列化步骤
- 将对象标记为序列化。在类的上一行标记
[Serializable],只有被标记的类创建的对象才能序列化 - 使用流将对象序列化到一个位置,举例:
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. 反序列化步骤
- 举例:
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部分类
- 作用:在项目开发时,有时候多个人可能会写好多个同名类,这时候就会造成冲突。
- 用法:在类的访问修饰符后面加一个
partial - 解释:使用部分类,相当于是把一个类分成了几部分,他们是互通的,可以把所有同名部分类看作一个类。因此两个同名的部分类分别写的成员可以互相用,同名的方法不能出现多次。
6、sealed密封类
- 作用:不想让自己的类被继承
- 用法:在类的访问修饰符后面加一个
sealed - 特点:不能被继承,可以继承其他类
7、ToString()是Object类的虚方法,子类可以重写。
8、interface接口(实现多态的第三种手段)
1. 作用
- 有时候,一个子类想继承多个父类,但是由于继承的单根性,不能实现。接口便是解决这个问题
- 不同类有同一个元素的时候使用
2. 解释
- 接口就是一个规范、能力
- 不同事物拥有同一种能力,这时候由于是不同事物,没办法写成父类,这时候就用到接口
3. 语法
[public] interface I..able
{
成员;
}英语中以i开头,以e结尾一般表示一种能力
4.特点:
- 一个子类继承一个接口,必须实现这个接口的成员
- 接口中的成员不允许添加访问修饰符,默认就是public。
- 只能写没有方法体的方法:方法、自动属性、索引器、事件。不允许写字段和构造函数。
- 接口中的成员不能有任何实现,让子类去做
- 不能实例化:静态类、抽象类、接口。因为接口里的方法没有实现。
- 接口与接口之间可以继承,没有单根性
- 接口不能继承一个类,而类可以继承接口(接口只能继承于接口,而类既可以继承接口,也可以继承类)
- 一个类如果既继承了接口,又继承了类,那么在语法上必须先写类,再写接口
5. 显式实现接口
- 作用:解决方法重名的问题。假如原类就有一个方法,继承的接口里面也有一个同名的方法,则自动认为接口里的方法已经被实现,因此需要显式实现。
- 举例:
public class Bird : IFlyable
{
public void Fly()
{
Console.WriteLine("鸟会飞");
}
void IFlyable.Fly()
{
Console.WriteLine("我是接口的飞");
}
}
interface IFlyable
{
void Fly();
}9、自动属性
- 举例:
public int Age
{
get;
set;
}- 虽然没有写字段,但是在生成的时候会自动生成一个字段
- 由于没有方法体,所以不能在get和set里面对读入数据进行处理,只能用构造函数的方法进行处理
10、Guid
- 作用:产生一个不会重复的编号
Guid.NewGuid()返回一个Guid类型的编号,在使用时通常.ToString()
评论