2015-10-20 67 views
2

我一直都有這個問題,但到目前爲止我一直都沒有跟上。爲什麼要在課堂上爲私人成員創建公共包裝?

這是一塊示例代碼:

爲什麼這樣做:

public class EmployeeInfo 
{ 
    int _EmpNo; 
    public virtual int EmpNo 
    { 
     get { return _EmpNo; } 
     set { _EmpNo = value; } 
    } 

    string _EmpName; 
    public virtual string EmpName 
    { 
     get { return _EmpName; } 
     set { _EmpName = value; } 
    } 
} 

時沒有什麼額外的,如計算或驗證,被獲取/設置過程中做了什麼?

這樣就夠了嗎?

public class EmployeeInfo 
{ 
    public int EmpNo { get; set; } 
    public string EmpName { get; set; } 
} 

另外,爲什麼virtual爲公共成員包裝?

+0

1)如果您所做的只是允許其他類從該屬性讀取和設置值,則不必使用私有成員。 2)虛擬關鍵字允許子類覆蓋屬性。 – Alex

+0

掌握一切公開的虛擬內容通常是一個糟糕的主意,並不是因爲它改變了功能,而是因爲這意味着當人們考慮應該如何實現繼承時,他們正在懶惰 – MikeT

回答

5

爲什麼這樣做?

自從在C#3.0中添加自動實現的屬性以後,真的沒有理由。它可能是遺留的代碼,尚未更改,舊習慣,或與C#3之前的代碼保持一致。

這樣就夠了嗎?

否 - 您已將virtual屬性轉換爲非虛擬屬性。所以它們並不完全等效。

相當於將

public class EmployeeInfo 
{ 
    public virtual int EmpNo { get; set; } 
    public virtual string EmpName { get; set; } 
} 

還有,爲什麼虛擬的公共成員的包裝?

所以派生類可以覆蓋邏輯屬性 - 添加驗證,變更通知等

何時縮短的形式實際上產生影響?

當支持字段被類的內部代碼引用(可以在編譯時檢測到),或者它們通過反射訪問(在運行時無法檢測到,或通過靜態代碼分析)。

「自動實現」屬性實際上獲取由編譯器創建的後臺字段,因此從這個意義上說,它們是相等的,如果引用僅支持字段的位置在屬性代碼中。

+0

'public virtual int EmpNo {get;組; }相當於? – SNag

+0

是的 - 請參閱我的編輯。 –

+0

請添加更多詳細信息?縮短的表格實際上何時會產生影響? – SNag

3

您有兩個問題。首先是將屬性更改爲auto implemented properties,它們應該是平等的,但是您刪除了virtual關鍵字,這使它們不同。

那麼,什麼是virtual。該關鍵字將允許派生類覆蓋該屬性的get/set

參見:virtual C#

虛擬關鍵字被用於修改的方法,屬性,索引,或 事件聲明,並允許它是在派生 類中重寫。

您與自動實現屬性類將是相同的,當你有:

public class EmployeeInfo 
{ 
    public virtual int EmpNo { get; set; } 
    public virtual string EmpName { get; set; } 
} 

稍後,您可以覆蓋一個屬性,保留其他維護父行爲,如:

public class ManagerInfo : EmployeeInfo 
{ 
    private int _EmpNo; 

    public override int EmpNo 
    { 
     get { return _EmpNo; } 
     set 
     { 
      if (value < 100) throw new Exception("EmpNo for manager must be greater than 100"); 

      _EmpNo = value; 
     } 
    } 
} 
2

取決於是否要公開或不公開地看到該字段,

如果您只使用decl中的字段aring類,那麼就不需要將其包裝在一個屬性,它只有在你需要公開其公開或向下,你應該有屬性

public string EmpName { get; set; } 

繼承樹只是一個編譯器捷徑

private string _EmpName; 
public string EmpName { 
    get{ return _EmpName;} 
    set(_EmpName = value; } 
} 

它們在功能上是相同的。 但是有些東西不會讓你做快捷方式,例如你想在屬性更改時提出事件。

那裏還有你使用虛擬這是一個繼承修飾符 虛擬指示代碼,它需要查看下來的繼承樹爲更新的實現。 所以在

class A 
{ 
    public string Data 
    { 
     get{return "A";} 
    } 
    public virtual string VData 
    { 
     get{return "A";} 
    } 
} 
class B:A 
{ 
    public new string Data 
    { 
     get{return "B";} 
    } 

    public override string VData 
    { 
     get{return "B";} 
    } 
} 

那麼如果你

A obj = new B(); 
obj.Data; //return A 
obj.VData; //return B 
+0

在前兩段中你很難說出什麼。沒有屬性。如果你的意思是領域,你也可以擁有公共領域,虛擬領域和私有領域。 – CodeCaster

+0

不好意思進入我的通用面向對象,在通用面向對象類有屬性和方法,飛行是交流#特定術語 – MikeT

+0

作爲公開或保護暴露字段是非常糟糕的做法,因爲面向對象的整個概念是,類是在控制它包含的數據意味着任何訪問數據必須通過類暴露的方法或屬性 – MikeT

1

它看起來像這種形式的代碼:

$type _$var; 
public virtual $type $var 
{ 
    get { return _$var; } 
    set { _$var = value; } 
} 

使用的工具,模板或片段產生。由於習慣幾乎沒有改變,工具,模板和片段幾乎無法更新,我猜它們是在自動實現的屬性(public $type $var { get; set; })引入C#語言之前創建的。

爲你展示的代碼,這是完全有效的等價:

public virtual $type $var { get; set; } 

正如你可以忽略自動實現的屬性並在需要時添加支持字段,驗證和一切。

0

擴展形式是傳統的方式來做到這一點:

public class MyClass 
{ 
    int _myInt; 

    virtual public int MyProperty 
    { 
     get 
     { 
      return _myInt; 
     } 
     set 
     { 
      _myInt = value; 
     } 
    } 
} 

然而,較短的形式被稱爲「自動屬性」,介紹了C#3.0。

public class MyClass 
{ 
    virtual public int MyProperty { get; set; } 
} 

這些代碼塊是等效的。這是保持代碼簡潔的好習慣。

有一點要考慮:你是不是能夠使內部變量protected與汽車性能,所以如果你創建一個派生類和override你的財產,你需要使用base.MyProperty訪問它,或者使用擴展形式。

相關問題