第三章 对象和类型
打好基础是关键!!!
废话不多说,开始。
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=0
ints[0]=0
Calling SomeFunction...
i=0
ints[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 Car private 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; } } }
通过这一章把类和结构的大体框架都读懂了,一些细节还不是很懂,多看程序,多写代码慢慢熟悉吧。