第三章-类和成员


1>类和结构
     (1)类和结构实际上都是创建对象的模板,每个对象都包含数据,并提供了处理和访问数据的方法。
        

```
class PhoneCustomer
{
public const string DayOfSendingBill ="Monday";
public int CustomerID;
public string FirstName;
public string LastName;
}
 
```
  
     (2)结构与类的区别是它们在内存中的存储方式(类是存储在堆(heap)上的引用类型,而结
构是存储在堆栈(stack)上的值类型)、访问方式和一些特征(如结构不支持继承)。较小的数
据类型使用结构可提高性能。在语法上,结构与类非常相似,主要的区别是使用关键字
struct 代替 class 来声明结构。
    实例:
```

struct PhoneCustomerStruct
{
public const string DayOfSendingBill = "Monday";
public int CustomerID;
public string FirstName;
public string LastName;
}
```
类和结构,都使用关键字 new 来声明实例:这个关键字创建对象并对其进行初始
化。
实例:
  PhoneCustomer myCustomer = new PhoneCustomer(); //works for a class
PhoneCustomerStruct myCustomer2 = new PhoneCustomerStruct(); // works for a struct
 
3>类成员
(1)类中的数据和函数称为类的成员。
    类中的所有成员都可以声明为 public(此时可以在类的外部直接访问它们) 或 private(此时,它们只能由类中的其他代码来访问)。
(2)数据成员
    1)数据成员包含了类的数据—— 字段、常量和事件。数据成员可以是静态数据(与整个类相关)或实例数据(类的每个实例都有它自己的数据副本)。对于面向对象的语言,类成员总是实例成员,除非用 static 进行了显式的声明。
    字段是与类相关的变量。
    访问字段:
```

PhoneCustomer Customer1 = new PhoneCustomer();
Customer1.FirstName = "Simon";
```

    2)const 关键字来声明常量。如果它们声明为 public,就可以在类的外部访问。
```

class PhoneCustomer
{
public const string DayOfSendingBill = "Monday";
public int CustomerID;
public string FirstName;
public string LastName;
}
```
4>函数成员
(1)函数成员提供了操作类中数据的某些功能,包括方法、属性、构造函数和终结器(finalizer)、运算符以及索引器。
     1)方法是与某个类相关的函数,它们可以是实例方法,也可以是静态方法。实例方法处理类的某个实例,静态方法提供了更一般的功能,不需要实例化一个类(例如 Console.WriteLine()方法)。
     2)属性是可以在客户机上访问的函数组,其访问方式与访问类的公共字段类似。
     3)构造函数是在实例化对象时自动调用的函数。它们必须与所属的类同名,且不能有返回类型。构造函数用于初始化字段的值。
     4)终结器类似于构造函数,但是在 CLR 检测到不再需要某个对象时调用。
     5)运算符执行的最简单的操作就是+和–。在对两个整数进行相加操作时,严格地说,就是对整数使用+运算符。
     6)就是对整数使用+运算符。

(2)方法
1)方法的声明
   1,每个方法都单独声明为 public 或 private
   2,方法的定义包括方法的修饰符(例如方法的可访问性)、返回值的类型,然后是方法名、输入参数的列表(用圆括号括起来)和方法体(用花括号括起来)。
  

```

[modifiers] return_type MethodName([parameters])
{
// Method body
}
```
     3,每个参数都包括参数的类型名及在方法体中的引用名称。但如果方法有返回值, return语句就必须与返回值一起使用,以指定出口点。


```

public bool IsSquare(Rectangle rect)
{
return (rect.Height == rect.Width);
}
```

     4,方法没有返回值,就把返回类型指定为 void,因为不能省略返回类型。
     5,注意方法可以包含任意多个 return 语句.


```

public bool IsPositive(int value)
{
if (value < 0)
return false;
    return true;
}
```
2)给方法传递参数
   1,参数可以通过引用或值传递给方法。在变量通过引用传递给方法时,被调用的方法得到的就是这个变量,所以在方法内部对变量进行的任何改变在方法退出后仍旧发挥作用。而如果变量是通过值传送给方法的,被调用的方法得到的是变量的一个副本。
   2,引用类型的对象只包含对象的引用,它们只给方法传递这个引用,而不是对象ᴀ身,所以对底层对象的修改会保留下来。相反,值类型的对象包含的是实际数据,所以传递给方法的是数据ᴀ身的副本。
   3)ref 参数
   1,通过值传送变量是默认的,也可以迫使值参数通过引用传送给方法。为此,要使用 ref关键字。如果把一个参数传递给方法,且这个方法的输入参数前带有 ref 关键字,则该方法对变量所作的任何改变都会影响原来对象的值:
    

```

static void SomeFunction(int[] ints, ref int i)
{
ints[0] = 100;
i = 100; //the change to i will persist after SomeFunction() exits
}
```

   2,在调用该方法时,还需要添加 ref 关键字:
  SomeFunction(ints, ref i);
   4)out 关键字
   1,使用 out 关键字来初始化。当在方法的输入参数前面加上 out 关键字时,传递给该方法的变量可以不初始化。该变量通过引用传送,所以在从被调用的方法中返回时,方法对该变量进行的任何改变都会保留下来。
  

```

static void SomeFunction(out int i)
{
i = 100;
}
public static int Main()
{
int i; // note how i is declared but not initialized
SomeFunction(out i);
Console.WriteLine(i);
return 0;
}
```
    5)方法的重载
    1,重载方法,只需声明同名但参数个数或类型不同的方法
   

```

class ResultDisplayer
{
void DisplayResult(string result)
{
// implementation
}
void DisplayResult(int result)
{
// implementation
}
}
```
     2,使用方法重载


```

class MyClass
{
int DoSomething(int x)
{
DoSomething(x, 10);
}
int DoSomething(int x, int y)
{
// implementation
}
}
```
    2,C#在重载方法的参数方面有一些小区别:
          ● 两个方法不能仅在返回类型上有区别。
          ● 两个方法不能仅根据参数是声明为 ref 还是 out 来区分。

(3)属性
1)属性的概念是:它是一个方法或一对方法,在客户机代码看来,它们是一个字段。
2)定义:

```

public string SomeProperty
{
get
{
return "This is the property value";
}
set
{
// do whatever needs to be done to set the property
}
}
```
get 访问器不带参数,且必须返回属性声明的类型。也不应为 set 访问器指定任何显式参数,但编译器假定它带一个参数,其类型也与属性相同,并表示为 value。

```

private string foreName;
public string ForeName
{
get
{
return foreName;
}
set
{
if (value.Length > 20)
// code here to take error recovery action
// (eg. throw an exception)
else
foreName = value;
}
}
```
注意:C#的区分大小写模式,使用相同的名称,但公共属性采用 Pascal 大小写命名规则,而私有属性采用 camel 大小写命名规则。
3)只读和只写属性
1,在属性定义中省略 set 访问器, 就可以创建只读属性。
2,在属性定义中省略 get 访问器,就可以创建只写属性。
4)属性的访问修饰符
属性可以有公共的 get访问器和私有或受保护的 set 访问器。这有助于控制属性的设置方式或时间。

(4)构造函数
1)构造函数的重载遵循与其他方法相同的规则。换言之,可以为构造函数提供任意多的重载,只要它们的签名有明显的区别即可:

```

public MyClass()
{
// construction code
}
public MyClass(int number)
{
// construction code
}
```
注意:如果提供了带参数的构造函数,编译器就不会自动提供默认的构造函数,只有在没有定义任何构造函数时,编译器才会自动提供默认的构造函数。

```

public class MyNumber
{
private int number;
public MyNumber(int number)
{
this.number = number;
}
}
```
一般使用 this 关键字区分成员字段和同名的参数。

2)把构造函数定义为 private 或 protected,不相关的类就不能访问它们。

```

public class MyNumber
{
private int number;
private MyNumber(int number)
{
this.number = number;
}
}
```
    注意:没有为 MyNumber 定义任何公共或受保护的构造函数。这就使
MyNumber 不能使用 new 运算符在外部代码中实例化(但可以在MyNumber 上编写一个公共静态属性或方法,以进行实例化)。
一下两种情况可用:
      ● 类仅用作某些静态成员或属性的容器,因此永远不会实例化。
      ● 希望类仅通过调用某个静态成员函数来实例化(这就是所谓对象实例化的类代理方法)。

3)静态构造函数
1,无参数的静态构造函数。这种构造函数只执行一次,而前面的构造函数是实例构造函数,只要创建类的对象,它都会执行。

```

class MyClass
{
static MyClass()
{
// initialization code
}
// rest of class definition
}
```
编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。

2, 从其他构造函数中调用构造函数
     两个构造函数初始化了相同的字段,显然,最好把所有的代码放在一个地方----构造函数初始化器。




 
 
 
 
 
 

    









 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值