【问题标题】:Understanding Access specifiers on Classes in C#了解 C# 中类的访问说明符
【发布时间】:2016-06-16 21:31:51
【问题描述】:

首先让我先说我确实了解访问说明符,我只是不明白在类中使用它们的意义。在方法上限制其范围是有道理的,但在类上,你为什么想要一个私有类,类的目的不是能够重用它们吗?

在 C# 中声明类时访问说明符的目的是什么?您什么时候使用它们?

谢谢

【问题讨论】:

  • 你应该阅读命名空间。
  • 当你想限制你的公共 API 的表面积是一个原因。想想封装以及这意味着什么……如果他们永远不需要接触它们,你真的希望你的消费者看到内部实现细节吗?在单个类的上下文中使用的私有嵌套类怎么样......等等
  • 您可以在private class 内开设一个大型班级。然后,您可以在周围的类中创建它的实例,但不能从外部创建。也许这个内部类太具体了,不应该在其他地方重用。
  • 嗯,不,C# 中类的目的是能够编写代码。封装是软件设计的基石。你期望一个类做的越少,它暴露给其他代码的可能性越小,这个类中的代码就越不可能出错。
  • 感谢大家提供的好信息。

标签: c# class access-specifier


【解决方案1】:

- 更新答案 2019 -

您好,您可以通过下表找到可访问性

【讨论】:

    【解决方案2】:

    我创建了一个应用程序来理解访问说明符。

    用代码代替理论会更容易理解。

    我在代码中添加了我的注释,以获得更好的指导。

    namespace ConsoleApplication1
    {
        //A normal public class which contains all different types of access-modifier classes in the assembly named 'ConsoleApplication1'
        public class Base
        {
            public class PublicBase
            {
                public static void fn_PublicBase()
                {
                    Console.WriteLine("fn_PublicBase");
                }
            }
            private class PrivateBase
            {
                public static void fn_PrivateBase()
                {
                    Console.WriteLine("fn_PrivateBase");
                }
            }
    
            protected class ProtectedBase
            {
                public static void fn_ProtectedBase()
                {
                    Console.WriteLine("fn_ProtectedBase");
                }
            }
    
            internal class InternalBase
            {
                public static void fn_InternalBase()
                {
                    Console.WriteLine("fn_InternalBase");
                }
            }
    
            protected internal class ProInternalBase
            {
                public static void fn_ProInternalBase()
                {
                    Console.WriteLine("fn_ProInternalBase");
                }
            }       
    
            //TIP 1:This class is inside the same class 'Base' so everything is accessible from above.Hurray!!
            class Base_Inside
            {
                public static void fn_Base_Inside()
                {
                    //All methods are easily accessible.Does not consider a modified indeed.
                    PublicBase.fn_PublicBase();
                    PrivateBase.fn_PrivateBase();
                    ProtectedBase.fn_ProtectedBase();
                    InternalBase.fn_InternalBase();
                    ProInternalBase.fn_ProInternalBase();
                }
            }
        }
    
        //Different class but inside the same assembly named 'ConsoleApplication1'
        public class Base_Sibling  : Base
        {        
            //TIP 2:This class is NOT in same class 'Base' but in the same assembly so  only protected is NOT accessible rest all are accessible.        
            public void fn_Base_Sibling()
            {
                PublicBase.fn_PublicBase();
                //PrivateBase.fn_PrivateBase();     //ERROR:Accesibility of 'protected'            
                ProtectedBase.fn_ProtectedBase();   //protected is accessible because Base_Sibling inherit class 'Base'. you can not access it via Base.ProtectedBase
                InternalBase.fn_InternalBase();
                ProInternalBase.fn_ProInternalBase();
            }
        }
    }
    

    现在了解内部、受保护的内部之间的区别, 我已经为以 Assembly_1 命名的项目添加了一个 解决方案。

    我已将 ConsoleApplication1Base 类继承到 Assembly_1Derived 类。

    namespace Assembly_1
    {
        //TIP:if it does not inherit class 'ConsoleApplication1.Base' then we can not access any thing beacuse this is different assembly.
        //TIP:only INTERNAL is NOT accessible , rest all are accessible from first assembly if it inherits class 'Soul'
        public class Derived : ConsoleApplication1.Base
        {
            public class PublicDerived
            {
                public static void fn_PublicDerived()
                {
                    PublicBase.fn_PublicBase();             //YES, becuase this is 'public'
                  //PrivateBase.fn_PrivateBase();           //No, becuase this is 'private'
                    ProtectedBase.fn_ProtectedBase();       //YES, becuase this is 'protected'
                  //InternalBase.fn_InternalBase();         //No, becuase this is 'internal'
                    ProInternalBase.fn_ProInternalBase();   //YES, becuase this is 'protected internal'
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      好吧,假设您希望一个类只能在她自己的程序集中访问:

      internal class Test
      

      假设您有两个类,一个在另一个内部(嵌套类):

      protected internal class TestA
      {
          private TestB _testB;
      
          private class TestB
          {
          }
      
          public TestA()
          {
              _testB = new TestB();
          }
      }
      

      TestB 类只能在 TestA 或她自己内部的方法/属性/构造函数内部访问。

      这同样适用于protected 修饰符。

      // 注意

      如果你不指定访问修饰符,默认为private,所以在我的例子中如下行:

      private TestB _testB;
      

      等于

      TestB _testB;
      

      这同样适用于类。

      特殊修饰符

      然后,protected internal 连接了两个修饰符,因此您只能从由该类派生的类访问同一程序集中的该类,即使它不在同一个组件。示例:

      组件 1:

      public class TestA : TestB
      {
          public TestB GetBase()
          {
              return (TestB)this;
          }
      
          public int GetA1()
          {
              return this.a1;
          }
      }
      protected internal class TestB
      {
          public int a1 = 0;
      }
      

      程序

      TestA _testA = new TestA(); // OK
      TestB _testB = new TestB(); // ERROR
      
      int debugA = new TestA().a1 // ERROR
      int debugB = new TestA().GetA1(); // OK
      
      TestB testB_ = new TestA().GetBase(); // ERROR
      

      来源

      Link (Access Modifiers)

      类型或成员可以被同一程序集中的任何代码访问, 但不是来自另一个程序集。

      类型或成员只能由同一类中的代码访问或 结构。

      类型或成员只能由同一类中的代码访问或 struct,或者在从该类派生的类中。

      类型或成员可以被同一个中的任何其他代码访问 程序集或引用它的其他程序集。

      【讨论】:

      • 如果我理解正确,这更适合创建公共 API 的人,如果我的假设是正确的,我可以让我的所有类没有访问说明符用于个人/本地项目,因为默认值为 @987654336 @,对吗?
      • 默认是private,通常人们只使用public,因为它很简单,不需要代码评估。但这一切都与模式、维护、灵活性和安全性有关。
      • 非常感谢您的澄清。
      【解决方案4】:

      使用访问说明符的最大好处是当其他人正在使用您的类时。通过明确指定对象中应该触摸和不应该触摸的内容,您可以保护对象的内部机制和完整性不被滥用或损坏。

      对于更大的类,如果您将所有内容都公开,您的代码用户也会更难使用 IntelliSense,这在您处理未知库时非常方便。

      【讨论】:

        【解决方案5】:

        我会给你一个内部类的例子。想象一下我有一些 DLL。形成这个 DLL,我只想公开一个名为 A 的类。然而,这个类A 应该可以访问 DLL 中的其他类 - 因此我会将 DLL 中的所有其他类设置为内部类。因此,从 DLL 中您只能使用类 A,而 A 仍然可以访问 DLL 中的其他类 - 但是您不能。

        【讨论】:

          猜你喜欢
          • 2018-01-30
          • 2011-04-16
          • 2016-11-11
          • 1970-01-01
          • 2023-03-16
          • 2017-09-17
          • 1970-01-01
          • 1970-01-01
          • 2012-06-05
          相关资源
          最近更新 更多