类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法。
类定义了每个类对象(称为实例)可以包含什么数据和功能。
定Person类
class PersonClass
{
public string FirstName;
public string LastName;
}
结构与类的区别是它们在内存中的存储方式(类是存储在堆(heap)上的引用类型,而结构是存储在堆栈(stack)上的值类型)、访问方式和一些特征(如结构不支持继承)。较小的数据类型使用结构可提高性能。但在语法上,结构与类非常相似,主要的区别是使用关键字 struct 代替 class 来声明结构。
struct PersonStruct
{
public int age;
public string name;
}
对于类和结构,都使用关键字 new 来声明实例:这个关键字创建对象并对其进行初始化。在下面
的例子中,类和结构的字段值都默认为 0
PersonClass P1 = new PersonClass();
PersonStruct P2 = new PersonStruct();
类中的数据和函数称为类的成员。Microsoft 的正式术语对数据成员和函数成员进行了区分。除了这些成员外,类还可以包含嵌套的类型(例如其他类)。类中的所有成员都可以声明为 public(此时可以在类的外部直接访问它们)或 private(此时,它们只能由类中的其他代码来访问)。与 Visual Basic、C++和 Java 一样,C#在这个方面还有变化,例如 protected(表示成员仅能由该成员所在的类及其派生类访问)
数据成员包含了类的数据-- 字段、常量和事件。数据成员可以是静态数据(与整个类相关)或实例数据(类的每个实例都有它自己的数据副本)。通常,对于面向对象的语言,类成员总是实例成员,除非用 static 进行了显式的声明。
PersonClass P1 = new PersonClass();
P1.FirstName = "song";
常量与类的关联方式同变量与类的关联方式一样。使用 const 关键字来声明常量。如果它们声明
为 public,就可以在类的外部访问。
class PersonClass
{
public const string Day = "Monday";
public string FirstName;
public string LastName;
}
函数成员提供了操作类中数据的某些功能,包括方法、属性、构造函数和终结器(finalizer)、运算
符以及索引器。
方法是与某个类相关的函数,它们可以是实例方法,也可以是静态方法。实例方法处理类的某个
实例,静态方法提供了更一般的功能,不需要实例化一个类(例如 Console. WriteLine()方法)。
ref 参数
函数执行后会改变参数的原值
方法定义:static void SomeFunction(int[] ints, ref int i)
方法调用:SomeFunction(ints, ref i);调用
out 参数
在 C 风格的语言中,函数常常能从一个例程中输出多个值,这是使用输出参数实现的,只要把输出值赋给通过引用传递给方法的变量即可。通常,变量通过引用传送的初值是不重要的,这些值会被函数重写,函数甚至从来没有使用过它们。编译器使用 out 关键字来初始化。在方法的输入参数前面加上 out 关键字时,传递给该方法的变量可以不初始化。该变量通过引用传送,所以在从被调用的方法中返回时,方法对该变量进行的任何改变都会保留下来。在调用该方法时,还需要使用 out 关键字,与在定义该方法时一样:
方法定义:static void SomeFunction(out int i);
方法调用:SomeFunction(out i); 调用
属性
属性(property)不太常见,因为它们表示的概念是 C#从 Visual Basic 中提取的,而不是从C++/Java中提取的。属性的概念是:它是一个方法或一对方法,在客户机代码看来,它们是一个字段。
public string SomeProperty
{
get
{
return "This is the property value";
}
set
{
// do whatever needs to be done to set the property
}
}
只读和只写属性
在属性定义中省略 set 访问器,就可以创建只读属性。同样,在属性定义中省略 get 访问器,就可以创建只写属性。但是,这是不好的编程方式,因为这可能会使客户机代码的作者感到迷惑。
属性的访问修饰符
C#允许给属性的 get 和 set 访问器设置不同的访问修饰符,所以属性可以有公共的 get 访问器和私有或受保护的 set 访问器。这有助于控制属性的设置方式或时间。在下面的例子中,注意 set 访问器有一个私有访问修饰符,而 get 访问器没有任何访问修饰符。这表示 get 访问器具有属性的访问级别。在 get 和 set 访问器中,必须有一个具备属性的访问级别。如果 get 访问器的访问级别是 protected,就会产生一个编译错误,因为这会使两个访问器的访问级别都不是属性。
自动实现的属性
如果属性的 set 和 get 访问器中没有任何逻辑,就可以使用自动实现的属性。这种属性会自动实现基础成员变量。
public string ForeName {get; set;}
public string ForeName {get; }
public string ForeName {get; private set;}
在C#中声明基本构造函数的语法与在Java 和C++中相同。下面声明一个与包含的类同名的方法,
但该方法没有返回类型:
无参构造函数:
public class MyClass
{
public MyClass()
{
}
//
}
有参构造函数:
public class MyClass
{
private int number;
public MyClass(int number)
{
this.number = number;
}
}
可以把构造函数定义为 private 或 protected,这样不相关的类就不能访问它们
public class MyClass
{
private int number;
private MyClass(int number)
{
this.number = number;
}
}
静态构造函数
C#的一个新特征是也可以给类编写无参数的静态构造函数。这种构造函数只执行一次,而前面的构造函数是实例构造函数,只要创建类的对象,它都会执行。编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。
public class MyClass
{
static MyClass()
{
// 初始化代码
}
}
方法的返回类值类型不同,或参数个数不同,或参数类型不同即可以实现方法重载
public int max(int a, int b)
public int max(int a, int b, int c)
public float max(float a, float b)
常量的概念就是一个包含不能修改的值的变量,常量是 C#与大多数编程语言共有的。但是,常
量不必满足所有的要求。有时可能需要一些变量,其值不应改变,但在运行之前其值是未知的。C#为这种情形提供了另一个类型的变量:只读字段。readonly 关键字比 const 灵活得多,允许把一个字段设置为常量,但可以执行一些运算,以确定它的初始值。其规则是可以在构造函数中给只读字段赋值,但不能在其他地方赋值。只读字段还可以是一个实例字段,而不是静态字段,类的每个实例可以有不同的值。与 const 字段不同,如果要把只读字段设置为静态,就必须显式声明。
public class DocumentEditor
{
public static readonly uint MaxDocuments;
static DocumentEditor()
{
MaxDocuments = DosomethingToFindOutMaxNumber();
}
}
partial 关键字允许把类、结构或接口放在多个文件中。
// Part1.cs
partial class PartClass
{
public void MethodOne()
{
}
}
// Part2.cs
partial class PartClass
{
public void MethodTwo()
{
}
}
静态类在功能上与使用私有静态构造函数创建的类相同。不能创建静态类的实例。使用 static 关键字,编译器可以检查以后是否给该类添加了实例成员。
静态类不需要示例化,即可进行调用
static class StaticClass
{
public static void HelperMethod()
{
}
}
// 调用静态类静态方法
StaticClass.HelperMethod();
所有的.NET 类都派生于 System.Object。实际上,如果在定义类时没有指定基类,编
译器就会自动假定这个类派生于 Object。
System.Object 方法