描述 private、protected、internal和public修飾符的
理解訪問權限存在的意義,各種訪問權限的作用,在代碼中靈活應用訪問權限。
【出現頻率】
★★★☆☆
【解答】
1.private修飾
private修飾符用於設置類或類成員的訪問權限僅爲所屬類的內部,private也被稱爲私有修飾符。某些時候需要訪問私有類成員時,可通過get和set訪問器讀取或修改。本例通過對類的私有成員及私有類的訪問,展示private修飾符的保護作用。在D:\web\NET\目錄下新建一個程序文件,並命名爲ModPrivate.cs,編寫代碼如代碼4.3所示。
代碼4.3 private修飾符示例:ModPrivate.cs
using System;
class ModPrivate
{
static void Main(String[] args)
{
Dog dg = new Dog("可卡");
Console.WriteLine("一隻小狗創建成功!");
Console.WriteLine("這隻"+dg.name + "的品種是:" + dg.type);
//由於參數類型爲字符串的構造函數是私有的,這裏不能直接創建實例對象
//Tiger tg = new Tiger("華南虎");
//由於Tiger類所嵌套的ZooTiger類是私有類,所以無法直接訪問
//Tiger.ZooTiger tz = new Tiger.ZooTiger();
Tiger tg = new Tiger(true); //參數類型爲布爾型的構造函數可創建Tiger類的對象
Console.WriteLine("\n一隻老虎創建成功!");
Console.WriteLine("這隻" + tg.name + "的品種是華南虎嗎?" + tg.ischinatiger);
}
}
class Dog //狗類名稱
{
internal string name = "小狗";
private string _type; //品種
internal Dog(string tp) //構造函數,直接給品種賦值
{
this._type = tp;
}
internal string type //type變量,get訪問器獲取私有成員_type的值
{
get { return this._type; }
}
}
class Tiger //虎類名稱
{
internal string name = "老虎";
private string _type; //品種
private bool _ischinatiger; //是否爲華南虎
private Tiger(string tp) //構造函數,直接給品種賦值
{
this._type = tp;
}
internal Tiger(bool chinatiger) //構造函數,直接給_ischinatiger賦布爾型值
{
this._ischinatiger = chinatiger;
}
internal string ischinatiger //ischinatiger變量,get訪問器獲取返回值
{
get
{
//由於同屬於Tiger類的內部,所以可創建ZooTiger私有類的對象
ZooTiger zt = new ZooTiger();
//返回字符串,內容爲私有成員_ischinatiger的值和ZooTiger的對象的name值
return this._ischinatiger + "(" + zt.name + ")";
}
}
private class ZooTiger
{
internal string name;
internal ZooTiger()
{
this.name = "動物園的老虎";
}
}
}
2.protected修飾符
protected修飾符用於設置類或類成員的訪問權限僅爲所屬類及子類的內部。本例通過對類的私有成員及私有類的訪問,展示private修飾符的保護作用。在D:\web\NET\目錄下新建一個程序文件,並命名爲ModProtected.cs,編寫代碼如代碼4.4所示。
代碼4.4 protected修飾符示例:ModProtected.cs
using System;
class ModProtected
{
static void Main(String[] args)
{
Console.WriteLine("請輸入所需創建老虎對象的品種(如東北虎、華南虎、孟加拉虎等):");
string input = Console.ReadLine(); //讀取用戶輸入,並存儲於input變量
string nm, tp;
if (input != "華南虎") //如果input變量存儲的不是"華南虎"字符串
{
Tiger tg = new Tiger(input); //創建Tiger類的對象,並傳遞input變量的值
nm = tg.name; //將tg對象的name屬性賦值給nm變量
tp = tg.type; //將tg對象的type屬性賦值給tp變量
}
else
{
ChinaTiger tg = new ChinaTiger(); //創建ChinaTiger類的對象
//將tg對象的name屬性(繼承於父類中聲明爲protected的屬性)賦值給nm變量
nm = tg.name;
//將tg對象的type屬性(繼承於父類中聲明爲protected的屬性)賦值給tp變量
tp = tg.type;
}
Console.WriteLine("\n一隻{0}創建成功!",nm);
Console.WriteLine("這隻{0}的品種是:{1}" ,nm,tp);
}
}
class Tiger //虎類名稱
{
protected string _name = "老虎";
protected string _type; //品種
internal Tiger() //無參數構造函數
{
}
internal Tiger(string t) //構造函數,直接給品種賦值
{
this._type = t;
}
internal string name //name變量,get訪問器獲取返回值
{
get
{
return this._name; //返回字符串,內容爲私有成員_name的值
}
}
internal string type //type變量,get和set訪問器獲取返回值或寫入值
{
get
{
return this._type; //返回字符串,內容爲私有成員_type的值
}
set
{
this._type = value; //爲私有成員_type賦值
}
}
}
class ChinaTiger : Tiger //華南虎類名稱
{
internal ChinaTiger() //構造函數,直接給品種賦值
{
this._type = "華南虎"; //直接賦值"華南虎"字符串給父類中繼承的_type屬性
}
}
3.internal修飾符
internal修飾符修飾的類或類成員的訪問權限爲同一程序集內部,C#默認的類訪問修飾符即爲internal。前面2個示例中,需要供類外部代碼訪問的成員都使用了internal修飾符,因爲這些類都處於同一程序集中。
4.public修飾符
public修飾符則爲公共訪問權限,對代碼的訪問沒有任何限制。大多數情況下須謹慎使用public修飾符,因爲濫用將影響類的封裝性,並且帶來安全隱患。
以下爲代碼的運行結果:
(1)在命令行下編譯ModPrivate.cs後,執行ModPrivate程序,其效果如圖4.5所示。
圖4.5 private修飾符示例
從本例代碼中可知,ZooTiger類無法在類的外部直接訪問,所有的私有成員只能在類的內部訪問,本例採用了get訪問器訪問了小狗和老虎的品種,並創建了ZooTiger私有類的對象。有的讀者可能會迷惑,如果同時使用get和set訪問器,private修飾符意義何在?其實很多程序中確實有這樣的做法,這樣做向類的外部屏蔽了私有成員的實現方法,同時也隱藏了私有成員的實際名稱,有利於封裝性。例如本例,get訪問器中有2步操作,而外界無法獲知。
(2)在命令行下編譯ModProtected.cs後,執行ModProtected程序,其效果如圖4.6所示。
圖4.6 protected修飾符示例
本例接收用戶的輸入,當輸入值爲“華南虎”時,創建ChinaTiger類的對象,並通過構造函數賦值“華南虎”字符串給_type字段。_type字段聲明中使用了protected修飾符,所以在Tiger類的子類(ChinaTiger類)中可被直接訪問。
注意:即使派生類和基類在不同程序集中,派生類仍可訪問基類的protected修飾符成員。讀者必須清楚的一點是,派生類繼承了所有基類的成員,只是無法直接訪問基類的private成員,但可訪問protected成員。
【分析】
面向對象編程的特徵之一就是封裝性,而類就是封裝性的典型體現。在生活中,人們不需要知道電器的內部構造,但是能很容易地使用電器,這就是封裝性。在項目中需要編寫很多功能類,在程序運行時只需要使用類所提供的功能,大部分類內部的代碼實現需要封裝,拒絕外部訪問。這樣大大增加了類的內部代碼安全和穩定性,多個功能類之間也減少了互相干擾的可能。訪問權限修飾符即可將類及類的成員劃分多種安全級別,根據不同需要設置訪問權限。
internal和public訪問修飾符是需要謹慎選擇的,多數情況下應該儘量使用internal訪問修飾符。
還有一種訪問修飾符,即protected internal修飾符,可在子類中或同一程序集內被訪問。如果要聲明成員只能被同一程序集內的派生類(子類)訪問,則應首先設置所屬類爲internal,成員設置爲protected 。
c#中public,private,protected,internal的區別 收藏
msdn的解釋如下:internal指的是同一個程序集,內部成員和類型纔是可以訪問的.內部訪問通常用於基於組件的開發,因爲它使一組組件能夠以私有方式進行合作,而不必嚮應用程序代碼的其餘部分公開
一個成員或類型只能有一個訪問修飾符,使用 protectedinternal 組合時除外。
命名空間上不允許使用訪問修飾符。命名空間沒有訪問限制。
根據發生成員聲明的上下文,只允許某些聲明的可訪問性。如果在成員聲明中未指定訪問修飾符,則使用默認的可訪問性。
不嵌套在其他類型中的頂級類型的可訪問性只能是 internal 或 public。這些類型的默認可訪問性是 internal。
嵌套類型是其他類型的成員,它們可以具有下表所示的聲明的可訪問性。
屬於 |
默認的成員可訪問性 |
該成員允許的聲明的可訪問性 |
enum |
public |
無 |
class |
private |
public protected internal private protected internal |
interface |
public |
無 |
struct |
private |
public internal private |
c#的細節(二)-修飾符 七月 6th, 2008
寫在最前面的話: 《c#的細節》是我當初學習c#時候,做的一些學習筆記的整理,現在回頭看來這些都是非常淺顯的知識,是c#非常細節的地方,同時也是不能忽略的地方,”細節決定成敗“,也許有些嚴重。我希望把這些整理出來,可以給初學者一個參考,也給自己一個溫故知新的機會。高手就不必花時間來看了。;-) ----------------------------------------------------------------------------------------------- 在c#的中修飾符的概念,最讓初學者有些頭痛了,理解起來也不是想象中那麼簡單,關鍵是不要搞亂了。 c#的修飾符大概分3類: 1、訪問型修飾符,就是控制所修飾成員的可訪問域,包括:public、private、protected、internal 和protected internal。其中只能protected internal 組合,其他都不能。 public:訪問不受限制。 private:訪問僅限於包含類型。只有包含該成員的類可以存取. protected:訪問僅限於包含類或從包含類派生的類型。只有包含該成員的類以及繼承的類可以存取. Internal:訪問僅限於當前程序集。只有當前項目(工程)可以存取. protected internal:訪問僅限於當前程序集或從包含類派生的類型。上面的概念好像很繞口。不過在如果你對面向對象大致瞭解的話,理解這些概念並不難,需要明確兩個東東:程序集和項目。這裏不詳細討論程序集和項目(如果你想全面瞭解有關程序集,項目,命名空間等東東,可以去看看這裏),你可以大致理解,一個項目可以是一個程序集。 public、private、proteced我覺得非常比較好理解,麻煩點就是Internal,只能在一個項目中使用,不能跨項目調用,只能自己的項目內使用,即使是子類也不能訪問。
namespace space1
{
internalclass Class1
{
publicint a
}
class Class2
{
publicvoid b()
{
Class1 cc = new Class1();
}
}
}
namespace space2
{
class App
{
staticvoid Main(string[] args)
{
space1.Class1 t_xA = new space1.Class1();//error
}
}
}
以上的代碼表明,Internal 是不能跨項目訪問的。對於protected internal 簡單些理解,就是protected 和internal 的並集。protected就只能被子類內部所訪問,於是它們的並集就是:同一個項目內或者子類內部可以訪問。如果既不是同一程序集也不是子類,就無法訪問。如下面的代碼所示:
namespace space3
{
public class Class1
{
internal protectedint a;
internalint b;
protectedint c;
}
publicclassclass2
{
publicvoid bbb()
{
Class1 t_x1=new Class1();
t_x1.a //ok
t_x1.b //ok
t_x1.b //error
}
}
publicclassclass3:Class1
{
publicvoid bbb()
{
base.a...//ok
base.b...//ok
base.c ...//ok
}
}
}
namespace space4
{
class Application1:space3.Class1
{
publicvoid a()
{
base.aa...
base.cc...
}
}
class bbb
{
publicvoid ccc()
{
space3..Class2 d = new space3.Class2();
d.a.. //error
d.b...//error
d.c... //error
}
}
}
2、類修飾符: abstract:標識一個類只能作爲其它類的基類. sealed:標識一個類不能被繼承. partial :局部類。將你的 class 分爲多個部分,編譯器會將多個部分拼合在一起。關於局部類部分你可以看看這裏 3、成員修飾符: abstract:指示該方法或屬性沒有實現. const:指定域或局部變量的值不能被改動. event:聲明一個事件. extern:指示方法在外部實現. override:對由基類繼承成員的新實現. readonly:指示一個域只能在聲明時以及相同類的內部被賦值. static:指示一個成員屬於類型本身,而不是屬於特定的對象. virtual:指示一個方法或存取器的實現可以在繼承類中被覆蓋. 注意:1、命名空間不能使用訪問修飾符。對命名空間沒有訪問是不受限制的,它的引入是主要是避免相同對象名的衝突。 2、如果在成員聲明中未指定訪問修飾符,則使用默認的可訪問性。
屬於 |
默認的成員可訪問性 |
該成員允許的聲明的可訪問性 |
enum |
public |
無 |
class |
private |
public protected internal private protected internal |
interface |
public |
無 |
struct |
private |
public internal private |