描述 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 |