第三章 对象和类型
打好基础是关键!!!
废话不多说,开始。
3.1 类和结构
类和结构都使用关键字New来声明实例
类中的数据和函数称为类的成员
在语法上,结构使用关键字struct,类用class来声明
3.2 类
1.数据成员
数据成员是包含类的数据—字段、常量和事件的成员。数据成员可以是静态数据。类成员总
是实例成员,除非用static进行显式的声明。2.函数成员
(1)方法
1)方法的声明
有返回值的和没有返回值的
//有bool类型返回值public bool IsSquare(Rectangle rect){return (rect.Height==rect.Width);}//无返回值public void IsSquare(Rectangle rect){}
2)调用方法
using System;namespace Wrox{ class MainEntryPoint { static void Main() { // Try calling some static functions Console.WriteLine("Pi is " + MathTest.GetPi()); int x = MathTest.GetSquareOf(5); Console.WriteLine("Square of 5 is " + x); // Instantiate at MathTest object MathTest math = new MathTest(); // this is C#'s way of // instantiating a reference type // Call non-static methods math.Value = 30; Console.WriteLine( "Value field of math variable contains " + math.Value); Console.WriteLine("Square of 30 is " + math.GetSquare()); } } // Define a class named MathTest on which we will call a method class MathTest { public int Value; public int GetSquare() { return Value*Value; } public static int GetSquareOf(int x) { return x*x; } public static double GetPi() { return 3.14159; } }}
3)给方法传递参数
分两种:①.引用传递,②.值传递
区别是看对变量所做的任何改变是否会影响原始对象的值
①.引用传递,会,②.值传递,不会
在C#中,除非特别说明,所有的参数都通过值来传递。对变量所做的任何改变不会影响原始对象的值。
如:
using System; namespace Wrox { class ParameterTest { static void SomeFunction(int[] ints, int i) { ints[0] = 100; i = 100; } public static int Main() { int i = 0; int[] ints = { 0, 1, 2, 4, 8 }; // Display the original values Console.WriteLine("i = " + i); Console.WriteLine("ints[0] = " + ints[0]); Console.WriteLine("Calling SomeFunction..."); // After this method returns, ints will be changed, // but i will not SomeFunction(ints, i); Console.WriteLine("i = " + i); Console.WriteLine("ints[0] = " + ints[0]); return 0; } } }
结果为:
ParameterTest.exe
i=0ints[0]=0Calling SomeFunction...i=0ints[0]=100注意,i的值保持不变,而在ints中改变的值在原始数组中也改变了。
4)ref参数
让方法使用引用传递。
对变量所做的任何改变都会影响原始对象的值
SomeFunction(ints, ref i);
5)out参数
该方法的该变量可以不用初始化
static void SomeFunction(out int i) { i=100; }
6)命名参数
参数要按方法的位置顺序写入,或者注明出。推荐注明出,这样程序更易读。
string FullName(string firstName, string lastName) { return firstName+””+lastName; }
FullName("John", "Doe"); FullName(lastName:"Doe",firstName:"John");
7)可选参数
int fun(int para1,int para2=0,int para3 = 0) {} //para1是必选参数,para2和para3为可选参数
8)方法重载
class ResultDisplayer { void DisplayResult(string result) { //implementation } void DisplayResult(int result) { //implementation }
(2).属性
属性(property)的概念是:它是一个方法或一对方法。
在C#中定义属性,可以使用下面的语法:
public string SomeProperty { get { return "This is the property value.这就是属性值。”; } set { //do whatever needs to be done to set the property. //设置属性值的代码 } }
1)只读和只写属性
在属性定义中省略set访问器,就可以创建只读属性。同样,在属性定义中省略get访问器,就可以创建只写属性。
2)属性的访问修饰符
属性可以有公有的get访问器和私有或受保护的set访问器。
3)自动实现的属性
如果属性的set和get访问器中没有任何逻辑,就可以使用自动实现的属性。
public int Age { get; set;}
这样的话,必须有两个访问器,即不能为只读,只写。
但是,每个访问器的访问级别可以不同。
public int{ get; private set;}
4)内联
c#代码编译的时候自动内联,不用程序员考虑。
(3).构造函数
1)静态构造函数
C#可以给类编写无参数的静态构造函数。这种构造函数只执行一次,只要创建类的对象,就会执行它。class MyClass{ static MyClass() { //initialization code } //rest of class definition}
编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。
2)从构造函数中调用其他构造函数
构造函数初始化器class Carprivate string description;private uint nWheels;public Car(string description, uint nWheels){this.description=description;this.nWheels=nWheels;}public Car(string description):this(description,4){}
构造函数初始化器在构造函数的函数体之前执行。
3.只读字段readonly关键字比const灵活得多,允许把一个字段设置为常量,但还需要执行一些计算,以确定它的初始值。
其规则是可以在构造函数中给只读字段赋值,但不能在其他地方赋值。
public class DocumentEditor{ public static readonly uint MaxDocuments static DocumentEditor() { MaxDocuments=DoSomethingToFindOutMaxNumber(); }}
3.3匿名类型var
var与new关键字一起使用时,可以创建匿名类型。var captain=new{person.FirstName, person.MiddleName, person.LastName};
3.4结构
class 是类,struct是结构结构不支持继承。对于结构构造函数的工作方式有一些区别。尤其是编译器总是提供一个无参数的默认构造函数,它是不允许替换的。使用结构,可以指定字段如何在内存中的布局。1.结构是值类型
注意,因为结构是值类型,new运算符并不分配堆中的内存,而是只调用相应的构造函数,根据传送给它的参数,初始化所有的字段。2.结构和继承结构不能从另一个结构中继承。3.结构的构造函数
结构不允许定义无参数的构造函数,不能在结构定义中给结构赋值。3.5 部分类partial
partial关键字允许把类、结构或接口放在多个文件中。//BigClassPart1.cs[CustomAttribute]partial class TheBigClass: TheBigBaseClass, IBigClass{ public void MethodOne() { })//BigClassPart2.cs[AnotherAttribute]partial class TheBigClass:IOtherBigClass{ public void MethodTwo() { }}
编译后,等价的源文件变成:
[CustomAttribute][AnotherAttribute]partial class TheBigClass:TheBigBaseClass, IBigClass, IOtherBigClass{ public void MethodOne() { } public void MethodTwo() { }}
3.6 静态类
使用static关键字,编译器可以检查用户是否不经意间给该类添加了实例成员。如果是,就生成一个编译错误。这可以确保不创建静态类的实例。static class StaticUtilities{ public static void HelperMethod() { }}
3.7 Object类
所有的.NET类都派生自Systsm.Object(1)System.Object()方法
1)ToString()方法int i=50;string str=i.ToString();
2)GetHashTable()方法
3)Equals()(两个版本)和ReferenceEquals()方法
4)Finaliz()方法5)GetType()方法6)MemberwiseClone()方法
3.8 扩展方法
扩展方法是静态方法,它是类的一部分,但实际上没有放在类的源代码中。假定Money类需要一个方法AddToAmount(decimal amountToAdd)。但是,由于某种原因,.程序集最初的源代码不能直接修改。此时必须做的所有工作就是创建一个静态类,把方法AddToAmount()添加为一个静态方法。对应的代码如下:namespace Wrox{ public static class MoneyExtension { public static void AddToAmount(this Money money, decimal amountToAdd) { money.Amount+=amountToAdd; } }}
通过这一章把类和结构的大体框架都读懂了,一些细节还不是很懂,多看程序,多写代码慢慢熟悉吧。