欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c# 類(lèi)型的字段和方法設(shè)計(jì)建議

 更新時(shí)間:2020年11月19日 12:00:39   作者:一只獨(dú)行的猿  
這篇文章主要介紹了c# 字段和方法設(shè)計(jì)建議,幫助大家更好的理解和使用c#編程語(yǔ)言,感興趣的朋友可以了解下

1、不要為抽象類(lèi)提供公開(kāi)的構(gòu)造方法

  抽象類(lèi)可以有構(gòu)造方法,但是抽象類(lèi)不能實(shí)例化。如果編程人員沒(méi)有制定構(gòu)造方法,編譯器會(huì)自動(dòng)生成一個(gè)默認(rèn)的protected構(gòu)造方法。下面是一個(gè)標(biāo)準(zhǔn)的簡(jiǎn)單抽象類(lèi):

abstract class MyAbstractClass
{
 protected MyAbstractClass( ) { }
}

  抽象類(lèi)的構(gòu)造方法不應(yīng)該是public或internal的。抽象類(lèi)設(shè)計(jì)的本意是只能讓子類(lèi)繼承,而不是用于生成實(shí)例對(duì)象。如果抽象類(lèi)是public或者internal的,它對(duì)于其他類(lèi)型來(lái)說(shuō)就是可見(jiàn)的,而這是不必要的,多余的。抽象類(lèi)只需對(duì)子類(lèi)可見(jiàn)即可。

2、可見(jiàn)字段應(yīng)該重構(gòu)為屬性

  字段與屬性有本質(zhì)的區(qū)別,屬性是方法。如下面的Person類(lèi)型:

class Person
{
 public string Name { get; set; }
}

  編譯器針對(duì)屬性Name編譯后,會(huì)生成一個(gè)字段和兩個(gè)方法。

  屬性相對(duì)于字段有如下優(yōu)勢(shì):

    1)可以為屬性添加代碼。屬性是方法,所以可以在方法內(nèi)對(duì)設(shè)置或獲取屬性的過(guò)程進(jìn)行編寫(xiě)代碼控制。如事件支持等。

    2)可以讓屬性支持線程安全。要讓屬性變成線程安全的,可以讓類(lèi)型自身去實(shí)現(xiàn)。如果讓字段支持線程安全,就只有依靠調(diào)用者本身實(shí)現(xiàn)。

    3)屬性得到VS編譯器支持,能實(shí)現(xiàn)自動(dòng)屬性的功能。自動(dòng)屬性的特點(diǎn)在LINQ中應(yīng)用十分廣泛,在匿名類(lèi)型中,它只能實(shí)現(xiàn)只讀的自動(dòng)屬性,但字段不支持。

    4)從設(shè)計(jì)的角度(面向?qū)ο螅?,公開(kāi)的字段也應(yīng)該使用屬性。改變字段的狀態(tài),類(lèi)型不會(huì)被通知到;而改變屬性的值,類(lèi)型支持則會(huì)被通知。

  綜上,如果一個(gè)類(lèi)型存在一個(gè)可見(jiàn)字段,那么它應(yīng)該被重構(gòu)為屬性。如果某個(gè)屬性只對(duì)內(nèi)部可見(jiàn),但不涉及上面4點(diǎn),則建議使用字段。

3、區(qū)別對(duì)待override和new

  override和new使類(lèi)型體系因?yàn)槔^承而呈現(xiàn)出多態(tài)性。多態(tài)是“面向?qū)ο笳Z(yǔ)言”的三個(gè)重要特性之一。多態(tài)要求子類(lèi)具有與基類(lèi)方法同名的方法,而override和new的有如下作用:

    1)如果子類(lèi)中的方法前面帶有new關(guān)鍵字,則該方法被定義為獨(dú)立于基類(lèi)的方法。

    2)如果子類(lèi)中的方法前面帶有override關(guān)鍵字,則子類(lèi)的對(duì)象將調(diào)用該方法,而不是調(diào)用基類(lèi)的方法。

  如果,對(duì)于父類(lèi)的方法在子類(lèi)中使用了new關(guān)鍵字,則兩個(gè)方法相互獨(dú)立。此時(shí),使用子類(lèi)類(lèi)型的對(duì)象調(diào)用方法時(shí),程序執(zhí)行的將是子類(lèi)類(lèi)型new的方法代碼;而如果將子類(lèi)類(lèi)型轉(zhuǎn)換為父類(lèi)類(lèi)型后,對(duì)象調(diào)用方法時(shí)將執(zhí)行的是父類(lèi)的方法代碼。

  如果使用了override關(guān)鍵字重寫(xiě)方法,那么不論子類(lèi)類(lèi)型的對(duì)象是否轉(zhuǎn)換為父類(lèi)類(lèi)型,調(diào)用方法時(shí)都將執(zhí)行的是子類(lèi)的代碼。

  如果對(duì)于子類(lèi)中,聲明與父類(lèi)相同函數(shù)名稱(chēng)的方法,但并不使用關(guān)鍵字new和override。編譯器在編譯后會(huì)提出警告,但不影響程序運(yùn)行。此時(shí),編譯器會(huì)默認(rèn)為是new的效果,所以輸出和顯示設(shè)置與new的效果一樣。

4、避免在構(gòu)造方法中調(diào)用虛成員

  在構(gòu)造方法中調(diào)用虛成員會(huì)出現(xiàn)意想不到的錯(cuò)誤。

class Program
 {
  static void Main(string[] args)
  {
   Chinese chinese = new Chinese();
  }
 }

 class Person
 {
  public Person()
  {
   InitSkin();
  }

  protected virtual void InitSkin()
  {
   //省略
  }
 }

 class Chinese:Person
 {
  Rece Rece;

  public Chinese():base()
  {
   Rece = new Rece() { Name = "趙銘" };
  }

  protected override void InitSkin( )
  {
   Console.WriteLine(Rece.Name);
  }
 }

 class Rece
 {
  public string Name { get; set; }
 }

  運(yùn)行該示例,會(huì)出現(xiàn)NullReferenceException:未將對(duì)象引用設(shè)置到對(duì)象的實(shí)例。

  在調(diào)用代碼中,需要?jiǎng)?chuàng)建一個(gè)Chinese的實(shí)例對(duì)象chinese。由于Chinese類(lèi)型有基類(lèi)Person,所以運(yùn)行時(shí)首先調(diào)用基類(lèi)的構(gòu)造方法。在基類(lèi)的構(gòu)造方法中,構(gòu)造函數(shù)會(huì)調(diào)用InitSkin虛方法。在程序運(yùn)行時(shí),調(diào)用的是子類(lèi)的InitSkin方法。在子類(lèi)的InitSkin方法中又在使用子類(lèi)的Rece變量。但這個(gè)時(shí)候,子類(lèi)的構(gòu)造函數(shù)還沒(méi)調(diào)用,因此Rece變量未實(shí)例化,但是InitSkin方法又在使用Rece變量,導(dǎo)致錯(cuò)誤。

5、成員應(yīng)優(yōu)先考慮公開(kāi)的基類(lèi)型或接口

  類(lèi)型成員在優(yōu)先考慮公開(kāi)基類(lèi)型或接口,會(huì)使得類(lèi)型支持更多的應(yīng)用場(chǎng)合。

  FCL中的集合類(lèi)型根據(jù)功能劃分有List<T>、Dictionary<TKey, TValue>、HashSet<T>等。例如,需要清空集合中的元素,返回空集合的方法Empty,如果不返回基類(lèi)型或者接口的情況下,就要求我們?yōu)槊總€(gè)集合類(lèi)型都實(shí)現(xiàn)該方法。但是,在FCL中實(shí)現(xiàn)了一個(gè)靜態(tài)類(lèi)型Enumerable,代碼如下:

 public static IEnumerable<TResult> Empty<TResult>()
 {
  return EmptyEnumerable<TResult>.Instance;
 }

  使用了泛型接口IEnumerable,所以所有集合子類(lèi)都可以不實(shí)現(xiàn)自己的Empty方法,做到項(xiàng)目的靈活應(yīng)用。

6、重寫(xiě)時(shí)不應(yīng)使用子類(lèi)參數(shù)

  重寫(xiě)時(shí),如果使用了子類(lèi)參數(shù),可能會(huì)偏離設(shè)計(jì)者的預(yù)期目標(biāo)。

  如存在以下繼承體系:

class Employee
{
}

class Manager:Employee
{
}

class Salary
{
 public void SetSalary(Employee e)
 {
  Console.WriteLine("職員被設(shè)置了薪水。");
 }
}  

class ManagerSalary:Salary
{
 public void SetSalary(Manager e)
 {
  Console.WriteLine("經(jīng)理被設(shè)置了薪水。");
 }
}

  類(lèi)型ManagerSalary中的SetSalary方法重寫(xiě)了Salary中的相同方法,但是參數(shù)采用了一個(gè)子類(lèi)的參數(shù)?,F(xiàn)在在程序中調(diào)用代碼如下:

public static void Main()
{
 ManagerSalary m = new ManagerSalary();
 m.SetSalary(new Employee());
}

  設(shè)計(jì)者的本意時(shí)為經(jīng)理設(shè)置對(duì)應(yīng)的薪水,但是實(shí)際調(diào)用的代碼卻設(shè)置了員工的薪水。因此,在重寫(xiě)時(shí)使用子類(lèi)參數(shù)有一定的風(fēng)險(xiǎn)。正確的方法時(shí)仍舊使用Employee類(lèi)型參數(shù),讓編譯器提醒我們要使用關(guān)鍵字new。

以上就是c# 字段和方法設(shè)計(jì)建議的詳細(xì)內(nèi)容,更多關(guān)于c# 字段和方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論