类
using System;
namespace HelloCar // namespace
{
class Factory // defination a car factory
{
public int MileCount=0;
public static int CarCount=0;
public Factory()
{
CarCount++;
}
public void Run(int n)
{
MileCount+=n;
}
}
class myWorld
{
static void Main()
{
Factory car1=new Factory();
Factory car2=new Factory();
car1.Run(5);
car2.Run(10);
Console.WriteLine("number of cars={}, total mile={}km",Factory.CarCount,car1.MileCount+car2.MileCount);
}
}
}
类的声明:修饰符 class 类名
类的成员:
- 数据成员:修饰符 类型 变量;
- 构造函数:修饰符 类名();
- 函数:修饰符 函数名();
- 内嵌类型:修饰符 内嵌类型 类型名{}
修饰符:
访问性修饰符 | 应用于 | 说明 |
---|---|---|
public | 所有类型和成员(析构函数除外) | 不限制对该类或成员的访问 |
private | 所有内嵌类型和成员 | 不能在定义此成员的类之外访问它,派生类也不行 |
protected | 所有内嵌类型和成员 | 只能从所在类和派生子类中访问 |
internal | 所有内嵌类型和成员 | 此成员只在当前程序集中可见 |
protected internal | 所有内嵌类型和成员 | 只在当前程序集的类和派生子类访问 |
注:非内嵌类型不能是私有的
没有添加访问修饰符的所有成员和内嵌类型都是private的
没有添加访问修饰符的所有非内嵌类型都是internal的
其他修饰符:
修饰符 | 应用于 | 说明 |
---|---|---|
new | 内嵌类型和所有成员 | 新成员隐藏父类中名称相同的成员 |
static | 所有成员(析构函数除外) | 静态成员属于类,不属于对象 |
virtual | 类和函数成员 | 虚成员可由派生类重写 |
abstract | 类和函数成员 | 抽象成员定义类型签名,不提供代码 |
override | 函数成员 | 重写了父类的虚成员或抽象成员 |
sealed | 类,方法和属性 | sealed密封类不能继承 |
extern | 仅用于静态方法 | extern成员在外部用另一语言实现,可修饰析构函数 |
静态类不构造任何对象,也不用来定义对象变量
数据成员
<Modifier> type var_name;
<Modifier> type var_name = initial_value;
数据成员有默认值;bool->false;数值->0;string->null;char->’\0’;引用->null
带有static静态类的字段,属于类所有,而不属于对象所有
可访问性约束:字段的访问性不应高于类的可访问性,下面的程序会报错
internal class A
{}
public C
{ public A a=new A();
}
改为public class A即可
函数成员
方法
<Modifier> reture_type name(tpye para1,type para2,...)
方法的签名:return_type name(type para1,…)
用签名可以区分两个不同的方法
double r=circleArea(9);
Console.WriteLine(r);
Car car1=new car();
car1.Run();
方法的调用有三种方式,第一种是直接调用;第二种是静态方法的调用,用类名.方法名;第三种是实例化方法的调用,用对象名.方法
方法的形参和实参
方法的参数有:值类型、引用型参数、输出型参数、数组型参数
值参数调用前后不改变原有值
值参数
static void Swap(int a1, int b1)
{
int t = a1;
a1 = b1;
b1 = t;
}
static void Main(string[] args)
{
int a = 6, b = 4;
Swap(a, b);
Console.WriteLine("a={0},b={1}",a,b);
Console.ReadKey();
}
返回值:a=6,b=4
引用参数
static void Swap(ref int a1, ref int b1)
{
int t = a1;
a1 = b1;
b1 = t;
}
static void Main(string[] args)
{
int a = 6, b = 4;
Swap(ref a, ref b);
Console.WriteLine("a={0},b={1}",a,b);
Console.ReadKey();
}
返回值:a=4,b=6
输出参数
static void Swap(int a, int b, out int a1, out int b1)
{
a1 = a; b1 = b;
int t = a1;
a1 = b1;
b1 = t;
}
static void Main(string[] args)
{
int a = 6, b = 4;
Swap(a, b,out a,out b);
Console.WriteLine("a={0},b={1}",a,b);
Console.ReadKey();
}
返回值:a=4,b=6
数组参数
数组参数是引用类型,只能允许一个一维数组参数放在参数列表的最后
static void Swap(params int[] a)
{
int t = a[0];
a[0] = a[1];
a[1] = t;
}
static void Main(string[] args)
{
int[] a = { 6, 4 };
Swap(a);
Console.WriteLine("a={0},b={1}",a[0],a[1]);
Console.ReadKey();
}
返回值:a=4,b=6
属性
属性用来封装字段,set用来设置字段,只包含set的属性是只写属性;get用来读取字段,只包含get的属性是只读属性;两个都包含的属性是读写属性
使用set设置字段,要首先判断字段的value的正确性
class Student
{
public string name;
private int age;
public int Age
{
set
{
if (value < 0)
Console.WriteLine("年龄不能小于0!");
else age = value;
}
get
{ return age; }
}
}
static void Main(string[] args)
{
Student s = new Student();
s.Age = -20;
s.Age = 30;
Console.WriteLine(s.Age);
Console.ReadKey();
}
属性相当于封装了一个字段value和两个方法set、get
自动属性:当属性只用来读或赋值时,可以用{set;get;}的自动属性
索引器
class Books
{
private string[] Title = new string[100];
private string[] Author = new string[100];
public string this[int i,string index]
{
set
{
if(index=="Author")
{
Author[i] = value;
}
else if(index=="Title")
{
Title[i] = value;
}
}
get
{
if (index == "Author") return Author[i];
if (index == "Title") return Title[i];
return "Unknown";
}
}
}
class Program
{
static void Main(string[] args)
{
Books books = new Books();
books[0, "Title"] = "征服美丽少女";books[0, "Author"] = "dsh";
books[1, "Title"] = "打败英俊少男"; books[1, "Author"] = "wtt";
for(int i=0;i<2;i++)
{
Console.WriteLine(books[i, "Title"] + " " + books[i, "Author"]);
Console.ReadKey();
}
}
}
索引器类似Python中的字典,通过关键字进行索引
索引器定义中,索引器名称必须是this,之后用[]来引导
运算符重载
class Complex
{
double r, i;
public Complex(double r0,double i0)
{
r = r0;i = i0;
}
public static Complex operator + (Complex c1,Complex c2)
{
Complex c = new Complex(0, 0);
c.r = c1.r + c2.r;
c.i = c1.i + c2.i;
return c;
}
}
class Program
{
static void Main(string[] args)
{
Complex c1 = new Complex(2, 1);
Complex c2 = new Complex(4, 3);
Complex c3 = c1 + c2;
}
}
重载运算符,修饰符必须是public static,要重载的运算符前有operator
构造函数
静态构造函数
在创建第一个实例或引用任何静态成员之前,系统自动调用静态构造函数来初始化类的静态字段,之后再也不调用。用户无法直接调用静态构造函数,也不可继承
class C
{ public int a;
public static int s;
static C()
{s=123;}
}
class Program
{ static void Main()
{ Console.WriteLine(C.s);
}
}
实例构造函数
class C
{ public int a;
public static int s;
static C()
{s=123;}
public C(int a)
{ this.a=a; }
public C()
{ a=456; }
}
class Program
{ static void Main()
{
C c;
c=new C(789);
Console.WriteLine(c.a);
}
}
可以定义多个实例构造函数,他们拥有不同的签名
当形参与字段同名时,用this关键字区分字段
析构函数
析构函数在对象脱离作用域时自动执行,定义语法如下
~class_name()
{}
不能带任何参数,也没有返回值,不能重载,不能继承,无法调用
一般不需要自己定义析构函数,除非类中打开了非托管资源