概念C#的近乎

《叩开C#的门》系列的四

四、定义C#的类

既然类类型是C#被最为根本、最普遍的品类,因此它是我要介绍的重要,实际上,C#丁的过多风味还可透过类类型来反映。

前都介绍,一个近似对象吃,主要包括字段、属性和艺术。不过除了,在看似项目受到还可以定义嵌套类,也得以定义一个常量。

对一个并未其他编程知识之初家而言,也许还答应介绍一下常量与变量。不过从其的讳便足以充分清晰地识别二者的区别,常量其值是不行更改的,而变量的价值则可修改,除非该变量是不过念之(如设置为readonly)。

极致好之常量的事例就是是圆周率值,这个价当是休转移的,如果保留小数点后七各,其值为3.1415926。然而一旦我们只要再三使用该值,则输入这么多数字自然不是好的选择,何况要用户要求圆周率更加可靠,需要保留更多之略微数个,要改起来就大艰苦了。因此我们得定义一个常量:
const PI = 3.1415926;

这会儿pi就象征了3.1415926,要用圆周率,直接取pi的价即可:
square = PI * radius;

注意点的表达式,其中PI是常量,在概念其经常,使用了const关键字;而square和radius则也变量,定义如下:
double square, radius;

要是定义了PI为常量,那么该类对象被确立以后,就非克改了,而变量是好改的。如下的代码是左的:
PI = 3.1415926535897;
square = PI * radius;

而下的片执代码则是不错的:
radius = 2.5;
square = PI * radius;

看似的字段其实为是变量。如雨后春笋三着之类User,就包含有字段m_name,m_password,m_tryCounter。它们的类分别吗string,string,int。字段仍然可以下public,internal,protected,private来修饰它。不过,我建议要非新鲜情形,不要拿字段修饰为public。因为,根据”对象封装”的规格,应竭尽避免将一个档次的字段以国有方式供于外部。毕竟,对于字段而言,对象对她的控制特别弱,一旦公开于外,则调用者可以比容易的对准那进展操作,尤其是形容操作,从而可能会见造成错误。例如,我们呢前定义之User类增加一个age(年龄)字段,假如自己拿该定义也public字段,如下所示:
public int Age;

这就是说调用者可能会见用Age的值设为负数:
user.Age = -5;

对于字段的概念而言,并无克判定这样同样栽不合常理的操作,因为我们对字段的刻画操作的控制无能为力。

大家可以看来,这里所谓的配段值,其实可以本着应于前面所言的目标的习性。例如姓名,年龄,就是一个用户之属性。如果字段非克装也public,那么调用者又怎么看它们啊?答案就是使用C#类中的property(属性)。

所谓“属性”,很特别程度足以当是针对“字段”的等同种包装,它利用同种植于称作“get/set访问器”分别控制对字段的读写操作,并表露一个属于性值,如Age属性:
private int m_age;
public int Age
{
 get {return m_age;}
 set
 {
  if (value < 0)
  {
   throw new ArgumentOutOfRangeException(“Age must be greater than or
equal to 0”);
  }
  m_age = value;
 }
}

地方的代码中,throw语句的意是废来一个好,我们小可以不失去理她,而是用注意力放到get和set访问器上。首先,我们定义了一个民用字段m_age,然后再定义一个集体属性Age。在该属性中,get返回私出字段的值m_age,而于set中,首先会见判定value的价值,如果小于0,那么这价值是黑的,就用摒弃来一个百般,停止向生执行,并告你针对Age值的装错误了。当然,我们吧堪呢value值设置双重严峻的求,例如不允许value大于150。至少人之年现在不曾超越150秋的吧。

可能会有人疑问value究竟是呀?它其实是C#中提供的严重性字,代表的便是若给给该属性之真的的价值,例如:
user.Age = 30;

这凡指向Age属性赋值,.Net会实行set访问器,而value值就是30。然后判断30是否小于0。显然不符合条件,不会见扔来怪,继续执行,将value值30予以给字段m_age。为什么要赋给m_age呢?让咱们再次看get访问器,它实际上就算是一个诵读操作,返回的值是什么?对了,就是字段m_age,如下所示:
user.Age = 30;     //set操作,将字段m_age设置为30;
Console.WriteLine(“User’s Age is {0}.”, user.Age);  
//get操作,将m_age的值取出;

这儿尽管会见当决定台下显示:
User’s Age is 30.

此外,对于有异的渴求,我们于用字段封装为性时,可以只是设置它的get访问器或者set访问器,这样是特性就是独读属性,或者仅写属性了。这样明显又便民对象的包裹。毕竟对于官字段而言,我们尽会得以决定它们也特读(设置为readonly),却无力回天设置也单写。

自打高达足见到,实际上属性就是本着字段进行一次封佯装。通过之包裹,使我们本着字段m_age的读写都具有了决定功能,至少本的Age属性能够决定赋值为负数的情了。这就算是性质的好处。

在C#
2.0遭到,除了可本着全部属性设置public等做客修饰符外,对中间的get/set访问器同样可安装访问修饰符,当然它们使遭肯定的界定。由于小限制及接口、重写关于,我小无会见介绍,在此地,我才介绍访问器和性能之看修饰符冲突问题。
1、如果一切属性被安装也public,则该访问器没有范围;
2、如果整属性让装置也protected
internal,则访问器的看修饰仅能够设置也internal,protected或者private中的同等栽;
3、如果整个属性为装也internal或者protected,那么访问器的走访修饰只能是private。
如下例:
public Class A
{
 private string m_text;
 private int m_count;
 public string Text
 {
  get {return m_text;}
  protected set { m_text = value;}
 }
 internal int Count
 {
  private get {return 5;}
  private set {m_count = value}
}
}

自从程序的真面目来拘禁,其实属性就是同一栽非常之方法,它一样于下的代码:
public int GetAge()
{
 return m_age;
}
public void SetAge(int age)
{
 m_age = age;
}

起这个含义及来了解get/set访问器的访问级别修饰,就再也爱懂了。实质上,所谓的访问器的走访级别修饰,不外乎就是指向章程进行访问级别修饰罢了。当然,C#倍受提供的性要比看字段的get/set方法尤其简便易行。一般而言,如要定义方法,应该是同一个目标的所作所为有关,例如系列三定义的User类中的SignIn()和SignOut()方法,它们代表的凡目标User的行事:登录以及离。

概念一个像样的方法,必须概括五只要素:方法修饰符,方法名,返回路,参数,以及方法体,例如Add方法:
public int Add(int x, int y)
{
 return x + y;
}

public即为咱的措施修饰符,它表示了该法能于看的级别。当然,修饰的方法的主要字还包static,virtual,abstract等,不过这些情节会当事后介绍。方法名当是Add了,自然属于方法的名字。返回路也int,代表该方法会返回一个结出,该结果类型为int类型。参数有星星点点只,分别吗x和y,它们的项目且是int。调用者可以透过参数传递值到方法体中,并对其进行操作。方法体则是花括号丁的内容。

只要Add方法是概念在类Calculator中,那么该方法的调用为:
Calculator cal = new Calculator();
int result = cal.Add(3,5);

通过对Add的调用,并传到3及5的参数,最后得到结果8,并赶回。因此,此时变量result的价值就吧8。而首先履代码,则是使用new关键字对Calculator类进行实例化,获得一个对象cal。通过对象cal,才足以调用Calculator类的官艺术、属性或字段。

胡而进行实例化呢?我们定义一个类类型,是吧调用者所祭的,否则即夺其意义了。但咱定义之这么一个类类型,仅仅是表示了某种格式而已,例如User类说明它是一个class,它具备了有字段、属性和措施。通过如此的定义,我们在采用这些品种的靶子时,.Net能够分辨它们。而若确实使调用这些品种对象,就必开展”实例化”,这个操作就会见当运作中,创建一个个靶,并吃在内存空间中供程序调用。就好比”人”就是一个类类型,而有一个具体的人数,才是让实例化的、真正在的对象。要使一个类类型被实例化,就用吗该品种提供”构造器”。构造器是同种新鲜的主意,它并未返回路,且其方法名和种名保持一致,如Calculator类的定义及它们的构造器:
public class Calculator
{
 public Calculator()
 {
 }
 public int Add(int x, int y)
 {
  return x + y;
 }
}

Calculator()方法就是是一个”构造器”,这个构造器并无参数,在C#蒙,也吃称作默认的构造器,即使不定义该构造器,.Net也会见为它默认创建。例如当Calculator类中,我们了可以删去Calculator()构造器的概念。然而,一旦我们定义了生参数的构造器时,则该默认构造器将无存,如果我们重新用不牵动参数创建实例的言语,就用显式创建该构造器了。例如之前的User类。如果姓名和密码是此类一个老大主要之性质,大部分状态下,如果要是创User对象时,都待就点儿只属性之价经常,我们就是足以呢User类专门创建一个构造器:
public class User
{
 public User(string name, string password)
 {
  m_name = name;
  m_password = password;
 } 
}

留意在是构造器中,接收两个参数name和password,并拿那个值赋给User类的字段m_name,m_password。因此,当我们由此如下的法门开创User类的实例时,我们创建的目标就是曾经颇具Name和Password的价值了:
User specUser = new User(“bruce zhang”, “password”);

而此时若是用下的措施创造User的实例,就会见并发错误:
User user = new User();
因为此时User类的默认构造器(即无参的构造器)已经不存,如一旦支持地方的实例化方式,就需要以User类的概念着补充加无参构造器。

是不是要吗一个类定义有参的构造器,应基于实际的用而一定。以User类而言,由于此类的Name和Password属性是一个对象必备的,那么建立这样一个构造器是发出必要的。因为要未享有这样的构造器,那么一旦前方组织之specUser就待因此底三行代码来完成:
User specUser = new User();
specUser.Name = “bruce zhang”;
specUser.Password = “password”;

留神,在一个好像的定义着,我们好采用this关键字来表示其类对象自我,通过this,可以看到这个类似的有所常量、字段、属性与章程,不管其是public还是private,或者其它访问级别。虽然此this指代的是相近对象自我,也就是说它表示的尽管是实例化所发出的靶子,但this的含义也特限于对象的中,从目标封装的思索来拘禁,它是吃装进了之,在靶外部是力不从心见到底。

譬如下面的定义:
public class Visitor
{
 public void Visit(Element e)
 {
  Console.WriteLine(“I was visited.”);
 }
}
public class Element
{
 public void Accept(Visitor v)
 {
  v.Visit(this);
 }
}

于Element类中,Accept方法则传出一个Visitor类型的参数值,在拖欠方式中,调用参数v的方法Visit,而Visit方法传入的凡Element类型的值,由于Accept方法本身即属于Element类,因此,我们可管该自传递及Visit方法吃,也就是代码中之this。

浅析如下的代码段:
Visitor v = new Visitor();
Element e = new Element();
e.Accept(v);

Element的实例e,执行了Accept()方法,该方式传入的参数是Visitor类的实例v。那么执行Accept方法,实质就是是当该道中尽v.Visit()方法,并透过this关键字将对象e本身传入,所以最后的结果是,打印如下的字符串:
I was visited。

当即此顺便取一下命名的要求。所谓命名规范,在作团队开支的早晚,是异常关键的。以本文为例,如何定义类名、字段名、属性名和艺术名,都是发讲究的。通常来说,类名、属性名和办法名都务求有所单词的首字母大写。如果是字段,那么除非是公私字段,一般而言,应将首先个单词的首字母小写。不过就为是变量命名的要求。由于在一个类似中,可能会见临时用到有的变量,而非是字段,为了区别一般变量和字段,C++的程序员喜欢在变量名前添加“_”符号,许多C#程序员也沿用了这习惯。不过我再欣赏为这些字段名前添加“m_”。命名一定要合并,尤其是当一个社中,不过类似于这些临时变量,或者非公有变量,对名字的限而掉一些,毕竟这些变量不见面被接近的调用者使用。此外,对于常量而言,最好定义也所有大写的讳,如前的概念之常量PI。

C#特意来同样效完整的命名规范,有趣味的可以友善去查一下特地的材料。此外,不同之铺面或还有部分特定的命名规范,在这边就不再赘言了。