c#提供面向对象的编程(包括封装、继承和多态)的完整支持。
1、“封装”意味着将一组相关的属性、方法和其他成员视为一个单元或对象。。
2、“继承”描述基于现有类创建新类的能力。
3、多态意味着可以有多个可互换使用的类,即使每个类以不同的方式实现相同的属性或方法
类和对象
“类”和“对象”分别描述对象的类型和类的实例。
定义类:
class Person
{
}
此外,c#在不需要支持继承和多态性的“结构”类型
定义结构:
struct Person
{
}
类成员
每个类都具有不同的“类成员”。类成员包括属性(用于描述类数据)、方法(用于定义类行为)和事件(用于在不同的类和对象中间提供通信)
属性和字段
字段和属性表示对象包含的信息。字段类似变量,可以直接读取和设置它们,要注意访问修饰符
定可以从类的实例中访问的字段:
public class Person
{
string Name;
}
属性具有get
和set
访问器,它们对设置和返回值的方式提供更多控制
c#允许创建私有字段来存储属性值,或者使用自动实现的属性,这些属性都是在后台创建此字段,并为属性过程提供基本逻辑。
定义自动实现的属性:
class Person
{
public string Namge{get;set;}
}
如果需要执行一些其他操作来写入和读取属性值,需要定义一个用于存储属性值的字段,并提供用于存储和检索该字段的基本逻辑:
class person
{
private string name;
public string Name
{
//将返回值存储在字段中
get => name;
//将值存储在字段中
set => name = value;
}
}
大多数属性的方法或过程都是可以设置或可以获取属性值。但是可以创建只读取或者只写属性来限制她们的修改或读取。在c#中,可以忽略get
或set
属性方法。但是,自动属性的实现不能只写。可以在包含类的构造函数中设置只读自动实现属性。
方法
“方法”是对象可以执行的操作。
定义类的方法:
class Person
{
public string SetName(string newName)
{
//写入代码
}
}
同一个方法,一个类型可以有多个实现,也叫“重载”,区别在于参数个数和参数类型的不同
重载方法:
class Person
{
public string SetName(string newName){}
public string SetName(int NewName){}
}
大多数情况下,方法是在类定义中声明的。同时,c#还支持“扩展方法”,这种方法允许你将方法添加到实际类定义中之外的现有类中。
构造函数
构造函数是一种类的方法,它们在创建给定类型的对象时自动执行。构造函数通常用于初始化新对象的数据成员。构造函数只能在创建类时运行一次。
创建类,定义构造函数:
public class Person
{
public Person()
{
//写入代码
}
}
构造函数中的代码始终在类中所有其他代码运行之前运行,我们可以使用重载的方式创建多个构造函数重载。
创建类,定义多个构造函数实现重载:
public class Person
{
public Person()
{
//写入代码
}
public Person(string name)
{
//写入代码
}
}
事件
类或对象可以通过事件向其他类或对象通知发生的相关事项。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。
1、若要在类中声明事件,请使用 event
关键字。
2、若要引发事件,请调用事件委托。
3、若要订阅事件,请使用 +=
运算符;若要取消订阅事件,请使用 -=
运算符。
嵌套类
在一个类中定义的类称为“嵌套类”。默认情况下,嵌套类是私有类
class Person
{
class GoodPeople
{
void Func()
{
Console.WriteLine("Func in GoodPeople")
}
}
}
如果要使用嵌套类,请使用嵌套容器类名称,后接一个点,再接嵌套类名称。
使用 Func
方法:
Person.GoodPeople gp = new Person.GoodPeoPle();
gp.Func();
访问修饰符
public
:同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。
private
:只有同一class或struct中的代码可以访问该类型或成员。
protected
:只有同一class或从该class派生的class中的代码可以访问该类型或成员。
internal
:同一程序集的代码都可以访问该类型或成员,但其他程序集中的代码不可以。
protected internal
:该类型或成员可由对其声明的程序集或另一程序集中的派生class
中的.任何代码访问
private protected
:只有在其声明程序集内,通过相同class
中的代码或派生自该class
的类型,才能访问该类型或成员。
实例化类
若要创建对象,需要先实例化类。即创建类实例
创建类实例:
Person p = new Person();
实例化类之后, 可以为该实例的属性和字段赋值,还可以调用类方法。
//为属性赋值
p.Name = "张三";
//调用类方法
p.SetName("张三");
若要在类的实例化过程中为属性赋值,请使用对象初始值设定项
Person p = new Person
{
Name = "张三";
}
静态类和成员
类的静态成员是指该类的所有实例共享的属性、过程和字段。
定义静态成员:
static class Person
{
public static string Name = "张三";
}
若要访问静态成员,请使用类的名称,但不要创建类的对象。
访问静态成员:
Console.WriteLine(Person.Name); //张三
c#中的静态类只有静态成员,无法进行实例化。静态成员也无法访问非静态属性、字段和方法。
匿名类型
匿名类型使你无需为数据类型编写类定义即可创建对象。
此时,编译器将为你生成类。该类没有可使用的名称,且包含在声明对象时指定的属性。
创建匿名类型的实例:
var person = new
{
Name = "张三",
Age =18
}
继承
通过继承,可以创建一个新类,它重用、扩展和修改另一个类中定义的行为。其成员被继承的类叫“基类”,继承这些类成员的类叫做“派生类”。c#中所有的类都隐式继承Object
类,该类为.NET层次结构,并为所有类提供低级别服务。
c#中不支持多重继承,只能为一个派生类指定一个基类。
从基类继承:
class Horse:Animal
{
}
默认情况下,可以继承所有类。但是可以指定该类不能用作基类,也可以创建只能作为基类的类。
指定该类不能用作基类:
public sealed class Animal{}
指定只能作为基类:
public abstract class Animal{}
重写
默认情况下,派生类继承其基类的所有成员。若希望更改继承成员的行为,则需要重写该成员。即,可以在派生类中定义方法、属性或事件达到新的实现。
用于控制重写属性和方法的修饰符:
c#修饰符 | 定义 |
---|---|
virtual | 允许在派生类中重写成员 |
override | 重写基类中定义的虚拟(可重写)的成员 |
abstract | 要求在派生类中重写类成员 |
new 修饰符 | 隐藏继承基类的成员 |
接口
和类一样,接口也定义了一系列属性、方法和事件。但与类不同的是,接口并不提供实现。它们有类来实现,并从类定义为单独的实体。接口表示一种约定,实现接口的类必须严格按其定义来实现接口的每个方面。
定义接口:
interface IPersonInterface
{
void GetName();
}
在类中实现接口:
class Person:IPersonInterface
{
void IPersonInterface.GetName()
{
//方法的实现
}
}
泛型
.NET Framework中的类、结构、接口和方法可以包括“类型参数”,该类型参数定义她们可以存储或使用的对象类型。最常见的泛型示例是集合,从中可以指定要存储在集合中的对象的类型。
定义泛型类:
public class Person<T>
{
public T Field;
}
创建泛型类的实例:
var person = new Person<string>();
person.Field = "张三";
委托
“委托”是一种类型,它定义方法签名,可以提供对具有兼容签名的任何方法的引用。你可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。
事件处理程序就是通过委托调用方法。例如winfrom中的事件,窗口传值
创建委托:
public delegate void PersonDelegate(string str);
创建对于委托指定的签名相匹配的方法的引用:
class PersonClass
{
//方法匹配PersonDelegate的签名
public static void PersonMethod(string message)
{
//写入代码
}
//实例化委托的方法
void PersonDelegate()
{
PersonDelegate pd = PersonMethod;//委托不要加括号
pd("person string");
}
}