ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 由C#访问控制修饰符的区别而学到的

由C#访问控制修饰符的区别而学到的

原创 Linux操作系统 作者:iDotNetSpace 时间:2010-02-05 13:19:20 0 删除 编辑
default,public,private,internal,protected,protected internal的区别,不知道是老师讲得太快,还是我实在是太笨了,反正听得一头雾水,相当头晕。突然冒出一个程序集的概念,而且不做任何解释或引入, 接着很快地引出“当前程序集内”,和“程序集外”两个概念。看着他演示的代码例子,偶的心情哇凉哇凉滴,只能用悲剧来形容。

  在自学的过程中,经常有这样的情况:你为了弄清一个概念,于是尝试去查阅这方面的书籍或者在线文档。然后你从对这个概念的解释中,又突然多出了 几个你完全没见过的新的概念。然后为了弄清那几个新的概念,你又得去查阅相关的文档,然而每个新发现的新概念的理解,又需要建立在理解另外的几个新的概念 的基础上——然而子又有子,子又有孙。子子孙孙,无穷匮也。于是有穷的生命和光阴就这样浪费在无穷的找答案的过程中,半天过去了,你似乎弄懂了,又好像完 全不懂。

  今天就是这种情况的典型例子。在几个关于.net的QQ群问了问题,和往常一样,一堆人在线,但是没有一个人理会。也许是大家都很忙,也许是我 问的题目太浅显,大家都不屑回答。去QQ群讨论技术问题,与其说投石问路,倒不如说投石于海。投在地上尚且掷地有声,投在海里就只能石沉大海了——下次有 问题不会了,绝对不去Q群问——于是又看了很多相关的网页,有些是一堆晦涩的文字,好不容易看完了,才发现没有一句看得懂,基本上等于白看;有些是风马牛 不相及的回答;而最惨的是,在你刚以为自己找到了答案的时候,又突然出现了一个跟你以为“正确”的答案,完全相反的说法,而你又不能判断谁对谁错。- -!

  综合了n多看上去比较正确的资料,加上自己的理解和很多次的代码测试,到此时此刻,脑子里对问题大概有个模糊的概念了。以下是自己的总结,与同样在自学道路上兢兢业业,苦苦求索的同学们共勉:

                                                             <关于什么是程序集>

  支持CLS(公共语言规范)的语言,源代码会编译为模块(由PE头,CLR头,元数据,MSIL组成)。而程序集Assembly包括一个或多个模块和资源文件的逻辑分组。它是可重用,安全性和版本控制的最小单位。

  程序集是一个部署单元,是托管应用程序的构件块。程序集是可重用的,不同应用程序可以使用同样的程序集。程序集在它们的元数据中携带了完整的自 描述信息(其中包括版本信息),允许CLR为特定的应用程序使用程序集的特定版本。这样就解决了所谓的“dll版本问题”——两个应用程序恰巧使用了名称 相同但版本不同的DLL,而更新其中一个应用程序的DLL就会使另一个应用程序不能运行。

   其实简单地说,程序集就是我们运行编译后产生的dll文件或者exe文件。它里面所包含的MSIL中间代码会在执行的时候,被CLR的JIT编译器根据本特定机器的实际情况进行特定的进一步优化,从而编译成相应的机器码。

  一个解决方案包括多个项目,一个项目包括多个文件。项目是跟程序集相对应的,一个项目就是一个程序集。

  命名空间是.net Framework类库的一种组织形式。命名空间中包含了一组功能或类型相近的类。在同一个命名空间的多个文件可以编译成多个程序集,可见,程序集跟命名空间并不是一一对应的关系。实际上,他们两者没有太大的联系。

                                                            <关于访问控制修饰符>

使用的代码编写ide工具:SharpDevelop2.0

编译方式:命令行

                              

结论一:在命令行用csc  name1.cs name2.cs格式进行编译的属于两个类同一程序集内,而用csc /t:library name1.cs用name1.cs文件先编译成类库(dll文件),然后再用类库和name2.cs关联编译的csc /r:name1.dll name2.cs,属于两个类不在同一个程序集内,即在程序集外的情况。

代码演示A:

Method.cs源文件的代码如下:

using System;
namespace Method
{
   public class MyMethod
   {
      public void publicMethod()
      {
         Console.WriteLine("This is a public Method.");
      }
      internal void internalMethod()
      {
         Console.WriteLine("This is an internal Method.");
      }
   }
}

 

Program.cs源文件的代码如下:

using System;

using Method;
namespace User
{
   class Program

   {
      public static void Main(string[] args)
      {
         MyMethod mm=new MyMethod();
         mm.publicMethod();
         mm.internalMethod();
      }
   }
}

当在命令行窗口输入csc Method.cs Program.cs把两个文件当成同一个程序集来编译并执行编译产生的Program.exe文件时,结果输出为:

    This is a public Method.
  This is an internal Method.

如图(1)所示:

         

                                                               图(1)

当在命令行窗口输入csc /t:library Method.cs把Method.cs文件编译成类库,然后把得到的类库跟Program.cs进行关联编译csc /r:Method.dll Program.cs时,则会出现“Program.cs(19,7): error CS0117:“Method.MyMethod”并不包“internalMethod”的定义”编译错误。如图(2)所示:

         

                                                               图 (2)

  由以上分析,容易知道结论一正确,同时,我们还可以知道程序集与命名空间并无一一对应的关系,因为在第一种编译方式中,两个文件分别属于Method命名空间和User命名空间,但是他们属于同一个程序集。

 

 

结论二:若类的成员方法前不加任何修饰符,则默认为private;若类名前不加任何修饰符,则默认为internal。

结论三:如各访问修饰符的访问范围统计表格容易知道:private只能被本类内部进行访问,而用public修饰,表示对访问没有任何限制。无论是用什么访问控制修饰符来修饰,本类内部都可以进行访问。

结论四:protected既可用于本类内部的访问,也可以用于子类对父类的访问(该子类和父类可以不在同一个程序集);

    internal对于同一个程序集内部都是可见的(不管两个类之间是不是继承关系)。

    由此可见,protected和internal修饰符各有 对方不能包含的范围,即protected可以进行跨程序集访问,而internal可以进行同一程序集内的非继承关系的两个类之间的访问。他们之间不是 包含与被包含的关系,两者的访问范围的大小不能进行比较。

结论五:虽然基类中用protected修饰的成员在其派生类中 可见,但是并不能在其派生类中实例化一个基类的对象,然后用该基类对象来调用protected修饰的方法(这样会出现编译错误)。正确的做法是在其派生 类中,实例化一个派生类的对象,然后又该派生类对象去调用基类protected修饰的方法。

结论六:protected internal修饰符相当于internal修饰符和protected修饰符的访问范围的取并集。也就是说,internal可以访问的范 围,protected internal可以访问,而protected可以访问的范围protected internal也可以访问。

代码演示B:

Method.cs源文件的代码:

using System;
namespace Method
{
   public class MyMethod
   {
       internal void internalMethod()

    {
         Console.WriteLine("This is an internal Method.");
    }
     protected void protectedMethod()

    {
       Console.WriteLine("This is a protected Method.");
    }
    internal protected void IntProMethod()
    {
       Console.WriteLine("This is an internal protected Method.");
    }
  }
}

 

Program.cs源文件代码:

using System;
using Method;
namespace User
{
  class Program           //Program类与MyMethod类之间并无继承关系,他们在同一个程序集中

  {

    public static void Main(string[] args)
    {
       MyMethod mm=new MyMethod();
       mm.internalMethod();

     mm.IntProMethod();
     }
  }
}

当用csc Method.cs Program.cs编译并执行Program.exe时,输出结果如下(如图三所示):

This is an internal Method.
This is an internal protected Method.

          

                                                        图(3)

这表明了,在同一程序集中,不管两个类是不是继承关系,internal和protected internal所修饰的成员都可以访问。

 

为了说明问题,现在对上面的Program.cs代码修改如下:

 

修改后的Program.cs源文件代码:

using System;
using Method;
namespace User
{
  class Program:MyMethod        //Program类继续于MyMethod类

  {

    public static void Main(string[] args)
    {
        Program p=new Program();
      p.protectedMethod();
        p.IntProMethod();
     }
  }
}

当把Method.cs通过csc /t:library Method.cs编译成类库文件,然后再把得到的类库文件跟Program.cs进行关联编译csc /r:Method.dll Program.cs,便可得到Program.exe文件,执行该文件,输出结果如下所示(如图4所示):

This is a protected Method.
This is an internal protected Method.

        

                                                          图(4)

这说明了虽然两个类不在同一个程序集中,但只要已经他们是继承关系,同样可以用子类的实例去调用基类中用protected和protected internal修饰符修饰的成员方法,即基类中用protected和protected internal修饰符修饰的成员方法在其派生类中是可见的。

综上所述,protected internal修饰符所能访问的范围是protected修饰符和internal修饰符的并集。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-626897/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-01-04

  • 博文量
    2376
  • 访问量
    5766209