C#中的类别与对象
概述
類的修飾詞,可以同時用一個或多個.
New 只能出現在巢狀類別內。它可指定類別隱藏具有相同名稱的繼承成員
public
protected
internal
private
abstract 表示抽象類,不能直接執行個體化,但可包含abstract方法,該類必須要被繼承.與sealed不能同時用.
sealed 表示封裝類,該類不可以被繼承,與abstract不能同時用.
类别可包含的成员种类:
成员 |
说明 |
常数 |
与类别关联的常数值 |
字段 |
类别的变量 |
方法 |
类别可执行的计算和动作 |
属性 |
与读取及写入类别具名属性关联的动作 |
索引子 |
与索引类别执行个体 (如数组) 关联的动作 |
事件 |
可由类别产生的告知 |
运算子 |
类别支持的转换及表达式运算子 |
建构函式 |
初始化类别执行个体或类别本身所需的动作 |
解构函式 |
要在类别执行个体永久宣告之前执行的动作 |
型别 |
类别所宣告的巢状型别 |
类别中成员的存取范围列表: 當未包含任何存取修飾詞時,將假設使用 private。
存取范围 |
意义 |
public |
不限制存取 |
protected |
仅限于存取这个类别,以及衍生自这个类别的类别 |
internal |
仅限于存取这个程序 |
protected internal |
仅限于存取这个程序,以及衍生自这个类别的类别 |
private |
仅限于存取这个类别 |
基底类别
类别会继承其基底类别的成员。继承意味着该类别会隐含包含其基底类别的所有成员,除基底类别的建构函式之外。衍生类别可将新的成员加到它所继承的成员内,但不能移除已继承成员的定义。
public class Point
{
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Point3D: Point
{
public int z;
public Point3D(int x, int y, int z): Point(x, y) {
this.z = z;
}
}
類別為資料結構,它可包含資料成員 (常數和欄位)、函式成員 (方法、屬性、事件、索引子、運算子、執行個體建構函式、解構函式和靜態建構函式) 和巢狀型別
下面这个类别包含了一些最常见函式成员的例子:
public class List | |
const int defaultCapacity = 4; |
常数 |
object[] items; |
字段 |
public List(): List(defaultCapacity) {} public List(int capacity) { |
建构函式 |
public int Count { public string Capacity { |
属性 |
public object this[int index] { |
索引子 |
public void Add(object item) { protected virtual void OnChanged() { public override bool Equals(object other) { static bool Equals(List a, List b) { |
方法 |
public event EventHandler Changed; |
事件 |
public static bool operator ==(List a, List b) { public static bool operator !=(List a, List b) { |
运算子 |
} |
1.字段
静态字段: 用 static 修饰词宣告。静态字段只能表示一个储存位置。不管一个类别建立多少个执行个体,还是只有一组静态字段。
执行个体字段:没有 static 修饰词宣告的字段。类别的每个执行个体都各自拥有一组该类别的所有执行个体字段。
只读字段:可以用 readonly 修饰词宣告。readonly 字段的设定只能出现为字段宣告的一部分,或出现在同一类别中的执行个体建构函式或静态建构函式中。
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte r, g, b;
public Color(byte r, byte g, byte b) {
this.r = r;
this.g = g;
this.b = b;
}
}
2方法
2.1静态和执行个体方法
静态方法: 用 static 修饰词宣告的方法, 静态方法不能在特定的执行个体上运作,而且只能存取静态成员。
执行个体方法: 不用 static 修饰词宣告的方法. 执行个体方法是在特定执行个体上运作,而且可以存取静态成员和执行个体成员。叫用执行个体方法的执行个体,可以当成 this 明确地存取。如果在静态方法中参考 this 将会发生错误。
2.2参数
实值参数:是用于输入参数传递。实值参数相当于区域变量,它们会从对该参数传递的自变量得到初始数值。修改实值参数不会影响对该参数传递的自变量。
参考参数: 用 ref 修饰词宣告,用于输入和输出参数传递。传递做为参考参数的自变量必须是变量;在方法执行期间,这个参考参数与该自变量代表相同的储存位置。
using System;
class Test
{
static void Swap(ref int x, ref int y) {
int temp = x;
x = y;
y = temp;
}
static void Main() {
int i = 1, j = 2;
Swap(ref i, ref j);
Console.WriteLine("{0} {1}", i, j); // Outputs "2 1"
}
}
输出参数: 用 out 修饰词宣告,用于输出参数传递。输出参数的性质和参考参数相似,不同的地方是,其呼叫端提供自变量的初始值并不重要。
using System;
class Test
{
static void Divide(int x, int y, out int result, out int remainder) {
result = x / y;
remainder = x % y;
}
static void Main() {
int res, rem;
Divide(10, 3, out res, out rem);
Console.WriteLine("{0} {1}", res, rem); // Outputs "3 1"
}
}
参数数组: 用 params 修饰词宣告,可以将不同数目的自变量传递给方法。参数数组必定是方法的最后一个参数,而且参数数组的型别必须是一维数组型别。
以下是它们的宣告方式示例:
public class Console
{
public static void Write(string fmt, params object[] args) {...}
public static void WriteLine(string fmt, params object[] args) {...}
...
}
以下是引用示例:
Console.WriteLine("x={0} y={1} z={2}", x, y, z);
等于下面的写法:
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine("x={0} y={1} z={2}", args);
2.3方法主体和区域变量
C# 要求区域变量必须明确设定,然后才可以省略它的值。
using System;
class Squares
{
static void Main() {
int i = 0;
int j;
while (i < 10) {//假设前面宣告的 i 没有包含初始值,编译器将会在后续使用 i 时报告有错误
j = i * i;
Console.WriteLine("{0} x {0} = {1}", i, j);
i = i + 1;
}
}
}
2.4虚拟、覆写和抽象方法
虚拟方法: 用virtual 修饰词宣告的方法.
覆写方法:用 override 修饰词宣告的方法. 用于覆写具有相同签名码的继承虚拟方法.
抽象方法: 用 abstract 修饰词宣告, 它是没有实作的虚拟方法, 只能存在于同样被宣告为 abstract 的类别中。抽象方法必须在每一个非抽象衍生类别中被覆写。
3.建构函式
执行个体建构函式:是一种实作初始化类别执行个体时所需之动作的成员。
静态建构函式:是在类别初次载入时,实作初始化类别本身所需之动作的成员。
和其它成员不同的是,执行个体建构函式不是继承的,而且除了该类别中实际宣告的执行个体建构函式外,类别没有其它的执行个体建构函式。如果没有提供类别任何执行个体建构函式,就会自动地提供一个不具参数的空白执行个体建构函式。
4.属性
属性是字段的自然延伸部分。它们都是具有关联型别的具名成员,并具有相同的存取语法。但是,属性和字段不同的地方是,属性并不会指定储存位置。相反地,属性具有存取子,该存取子在读取或写入属性值时,会指定要执行的陈述式。
C# 也同时支持执行个体属性和静态属性.
属性的存取子可以是虚拟。属性宣告如果包含 virtual、abstract 或 override 修饰词,它也会套用到该属性的存取子。
5.索引子
索引子是让对象可以如同数组一样索引的成员。索引子宣告就像属性一样,不同的是,成员名称为 this,后面跟着撰写于分间符号 [ 和 ] 之间的参数清单。这些参数可以在索引子的存取子中找到。
像属性一样,索引子可以是读写、只读和唯写,而且索引子的存取子也可以是虚拟。
索引子可以多载,也就是说,类别可以宣告多个索引子,但是它们的参数个数和型别必须不同。
6.事件
事件是可以让类别或对象提供告知的成员。事件的宣告就像字段一样,不同的是,宣告包含了 event 关键词,而且型别必须是委派型别。
在需要控制事件基础储存的进阶状况中,事件的宣告可以明确加入 add 和 remove 存取子 (类似属性的 set 存取子)。
下面范例将一个事件处理例程附加到 List 的 Changed 事件
using System;
class Test
{
static int changeCount;
static void ListChanged(object sender, EventArgs e) {
changeCount++;
}
static void Main() {
List names = new List();
names.Changed += new EventHandler(ListChanged);
names.Add("Liz");
names.Add("Martha");
names.Add("Beth");
Console.WriteLine(changeCount); // Outputs "3"
}
}
7.运算子
运算子是一种定义类别执行个体的表达式运算子运作方式的成员。运算子可定义为下列三种类型:一元运算子、二元运算子和转换运算子。所有的运算子都必须宣告为 public 和 static。
using System;
class Test
{
static void Main() {
List a = new List();
a.Add(1);
a.Add(2);
List b = new List();
b.Add(1);
b.Add(2);
Console.WriteLine(a == b); // Outputs "True"
b.Add(3);
Console.WriteLine(a == b); // Outputs "False"
}
}
8.解构函式
解构函式是实作解构类别执行个体时所需动作的成员。解构函式不能具有参数、存取范围修饰词,也不能被明确地叫用。执行个体的解构函式会在内存回收时自动叫用。
内存回收行程可以让您更自由地决定回收对象及执行解构函式的时间。更明确地说,解构函式引动过程的时机不再具有决定性,而且解构函式可以在任何执行绪上执行。基于上述以及一些其它的理由,只有在没有其它可行的解决办法时,类别才需要实作解构函式。