国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

C#箴言之用屬性來訪問類的私有成員

2024-07-21 02:28:58
字體:
來源:轉載
供稿:網友

  在程序中,難免要訪問某個對象的私有成員。那么以前實現這類功能的方法有兩種,第一種方法最簡單,就是把成員訪問符從“private”改為“public”即可;而另一個就是提供公有的成員訪問函數來進行訪問。那么現在用c#編寫程序,就不再需要采用前面所說的兩種方法了,而直接使用屬性來完成。

  首先來看看三種方法的如何實現以及調用的,這里用一個例子來說明,即訪問“employeeinfo”類的私有成員strname,具體如下表格所示。

 private string strname;訪問方法
修改成員訪問符修改:
private string strname;
為:
public string strname;
employeeinfo empnew...;
string strnamevalue = empnew.strname;
empnew.strname = "me";
公有成員函數增加如下兩個成員函數:
public string getname()
{
 return strname;
}

public void setname( string name )
{
 strname = name;
}
employeeinfo empnew...;

string strnamevalue = empnew.getname();

empnew.setname( "me" );
屬性增加如下屬性:
public string name
{
 get{ return strname;}
 set{ strname = value; }
}
employeeinfo empnew...;
string strnamevalue = empnew.name;
empnew.name = "me";

  那么這三種方法有什么區別呢,用如下的表格,可以更好的說明三者的區別。

 類的封裝性代碼安全性代碼繁瑣性代碼效率
修改成員訪問符破壞類的封裝存在潛在危險簡便最高
公有成員函數沒有破壞安全繁瑣,而且調用不直接最低
屬性沒有破壞安全簡便僅次于第一種方法
    (備注:這里用紅色表明每一子項中最不好的)

  因此可以看出使用屬性不但沒有破壞類的封裝性,沒有減弱代碼的安全性,而且和第一種方法一樣簡便,只是在效率方面要略低于第一種方法。但總體看來,在c#中用屬性來訪問類的私有成員是不二的選擇。

  不過對于使用屬性,以及如上表格所說的,難免會有人產生如下一些疑問。

  疑問一:就是用屬性是否能達到成員函數那樣的效果,即完成復雜的代碼操作。

  其實屬性的底層實現是借助于成員函數,只不過這部分轉換是由系統幫忙做的,所以在編寫屬性的時候,可以像編寫成員函數一樣,即在成員函數中所能寫的代碼片斷,完全可以在屬性中套用。下面就貼出屬性所轉換的微軟中間語言(msil)代碼。

.property instance string name()
{
 .get instance string namespace.employeeinfo::get_name()
 .set instance void namespace.employeeinfo::set_name(string)
}// end of property employeeinfo::name

.method public hidebysig specialname instance string get_name() cil managed
{
 ...
}// end of method employeeinfo::get_name

.method public hidebysig specialname instance void set_name(string 'value') cil managed
{
 ...
}// end of method employeeinfo::set_name

  如上就是前面employeeinfo類的name屬性所轉換的中間語言代碼(不過省略了函數的具體實現代碼,因為這里并不是為了研究中間語言代碼,如果需要對這部分有更多地了解,參看中間語言相關書籍)。

  疑問二:就是用屬性的效率是否僅次于第一種方法。

  從上面很容易看出,屬性在編譯的時候會轉換成和成員函數一樣的代碼,那么它的效率應該和成員函數是一樣的。其實并不是這樣,因為jit編譯器會把屬性所轉換成的兩個成員函數作為內聯函數,這樣效率會提高很多。(注:內聯函數是代碼被插入到調用者代碼處的函數,通過避免函數調用所產生的額外開銷,從而提高執行效率。不過書中也提到,即使不是內聯函數,成員函數相對于方法一的效率損失也是微乎其微的。)

  用c#寫程序,一提到屬性,大家都會編寫。其實在屬性中,可以產生很多應用,接著來就分別說明。

  <!--[if !supportlists]-->1. <!--[endif]-->在屬性中使用索引符,例如像“arraylist[i]”來訪問arraylist某個成員。這里需要注意的是,屬性名以及索引參數的編碼格式是固定的,如“this […]”。不過索引參數可以是多個,而且不光支持整型參數,還可以使用其他類型參數。例如:

public returnvaluetype this[ partype1 parvalue1, partype2 parvalue2]
{
 get{...}
 set{...}
}

  <!--[if !supportlists]-->2. <!--[endif]-->可以給屬性操作加上互斥鎖,以防止多線程操作時而產生的并發錯誤,具體如下。

public string name
{
 get
 {
  lock(this)
  {
   return strname;
  }
 }
 set
 {
  lock(this)
  {
   strname = value;
  }
 }
}

  <!--[if !supportlists]-->3. <!--[endif]-->書上還提到屬性的其他應用,例如:通過接口來實現在一個類中同時提供只讀屬性以及非只讀屬性。但是我個人認為,雖然這樣可以實現,但是會產生歧義,即在一個類中提供兩個不同版本的屬性,破壞了類的一致性,所以我并不推薦這么做。

  接著,要說說編寫屬性的時候,需要注意些什么,我個人認為有如下兩點大的方面。

  第一個就是編寫屬性get部分的時候,如果當前屬性的類型是引用類型的話,且不想通過屬性來修改局部成員的話,最好返回局部成員的copy,而不是成員本身。

  例如:

public class class1
{
 string _data;
 public class1( string data )
 {
  _data = data;
 }

 public string data
 {
  get{ return _data;}
  set{ _data = value;}
 }
}

public class class2
{
 private class1 myclass1 = null;
 public class1 class1
 {
  get{ return myclass1; }
 }

 public string data
 {
  get{ return myclass1.data;}
 }

 public class2( string data )
 {
  myclass1 = new class1( data );
 }
}

  如果按照如上所寫,那么class2對象可以通過class1.data屬性訪問和修改局部成員myclass1某些值,這樣就可以修改了myclass2的私有成員myclass1的值,即會產生潛在錯誤。

  例如:

class1 myclass1 = myclass2.class1;
myclass1.data = "test2";

  如何避免這類錯誤呢,那么首先需要修改class1屬性的編寫,其次在class1類需要提供clone函數或者其他copy函數,具體如下:

public class class1:icloneable
{
 string _data;
 public class1( string data )
 {
  _data = data;
 }

 public string data
 {
  get{ return _data;}
  set{ _data = value;}
 }

 #region icloneable members

 public object clone()
 {
  // todo: add class1.clone implementation
  return new class1( _data );
 }
 #endregion
}

public class class2
{
 private class1 myclass1 = null;
 public class1 class1
 {
  get{ return myclass1.clone() as class1; }
 }

 public string data
 {
  get{ return myclass1.data;}
 }

 public class2( string data )
 {
  myclass1 = new class1( data );
 }
}

  第二個需要注意的是編寫屬性set部分的時候,這里需要對參數進行有效性檢查。因為屬性是外界修改類的私有成員的入口,為了避免因為私有成員不正確而產生的錯誤,所以在進行屬性set的時候要進行有效性檢查,從而保證私有成員對于整個類來說是有效的。

  那么在實際應用當中,與屬性密切相關的就是實現兩個窗體之間數據訪問,這可能是寫winform程序最基本的。不過很遺憾的是,網上在回答此類問題的時候,很多人都建議用第一種方法來解決。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 津南区| 丘北县| 巴彦淖尔市| 巴林右旗| 灵川县| 富锦市| 盱眙县| 特克斯县| 镇巴县| 开封县| 布尔津县| 望奎县| 湖南省| 志丹县| 伊金霍洛旗| 贞丰县| 汤阴县| 石台县| 扎鲁特旗| 茂名市| 车致| 东山县| 灵山县| 靖州| 白城市| 澎湖县| 阳泉市| 东至县| 晋中市| 河津市| 蒙自县| 武陟县| 柳河县| 容城县| 昭通市| 泗阳县| 云龙县| 桃江县| 景泰县| 汤阴县| 江山市|