C#类访问修饰符

本文详细介绍了C#中的访问修饰符,包括public、protected、internal及private等,并通过示例代码展示了不同修饰符在实际编程中的应用。此外,还讨论了如何在不同场景下选择合适的访问级别。
微软官方文档
http://msdn.microsoft.com/zh-cn/library/wxh6fsc7(VS.80).aspx

访问修饰符是一些关键字,用于指定声明的成员或类型的可访问性。访问修饰符有四个:

public protected internal private

声明的可访问性

含义

public

访问不受限制。

protected

访问仅限于包含类或从包含类派生的类型。

internal

访问仅限于当前程序集。

protected internal

访问仅限于从包含类派生的当前程序集或类型。

private

访问仅限于包含类型。

一个成员或类型只能有一个访问修饰符,使用 protected internal 组合时除外。

命名空间上不允许使用访问修饰符。命名空间没有访问限制。

根据发生成员声明的上下文,只允许某些声明的可访问性。如果在成员声明中未指定访问修饰符,则使用默认的可访问性。

不嵌套在其他类型中的顶级类型的可访问性只能是 internal 或 public。这些类型的默认可访问性是 internal。

嵌套类型是其他类型的成员,它们可以具有下表所示的声明的可访问性。

属于

默认的成员可访问性

该成员允许的声明的可访问性

enum

public

class

private

public

protected

internal

private

protected internal

interface

public

struct

private

public

internal

private

范例如下:

publicTest

namespace publicTest
{
    class Point
    {
        public int x;
        //private int x;
        //protected int x;
        //internal int x;
        public int y;
    }
}
namespace publicTest
{
    class MainClass
    {
        static void Main()
        {
            Point p = new Point();
            // Direct access to public members:
            p.x = 10;
            p.y = 15;
            Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
            Console.ReadLine();
       }
    }
}

在同一程序集下,定义Point类下的成员为public与internal,可直接通过 MainClass 访问 Point 的公共成员 x 和 y。

protectedTest

namespace protectedTest
{
    class A
    {
        protected int x = 123;
        //public int x = 123;
    }
}
namespace protectedTest
{
    class B : A
    {
        static void Main()
        {
            A a = new A();
            B b = new B();
            // Error CS1540, because x can only be accessed by
            // classes derived from A.
            // a.x = 10;

            // OK, because this class derives from A.
            b.x = 10;

            //Console.WriteLine("{0} {1}", a.x, b.x);
            Console.WriteLine(b.x);
            Console.ReadLine();
       }
    }
}

在B中调用类A的构造函数,创建一个对象a。然后获取a.x会报CS1540错误,在网上也搜了好久。搜到了如下信息:protected类型并不是能够被派生类随心所欲的访问,而是有条件的,访问必须是通过派生类类型发生时,在派生类中的基类的protected类型成员才能够被访问,这里就很清楚了上面的代码并不是通过派生类的类型访问的,而是通过基类的类型访问的,此时此刻,protected和private十分的相似,只不过,protected类型成员能够被派生类所继承并且能够通过派生类类型访问罢了。

namespace protectedTest
{
    class Point
    {
        protected int x;
        protected int y;
    }
}
namespace protectedTest
{
    class DerivedPoint : Point
    {
        static void Main()
        {
            DerivedPoint dp = new DerivedPoint();

            // Direct access to protected members:
            dp.x = 10; dp.y = 15;
            
            Console.WriteLine("x = {0}, y = {1}", dp.x, dp.y);
            Console.ReadLine();
       }
    }
}

privateTest

namespace privateTest
{
    class Employee
    {
        private string name = "FirstName, LastName";
        private double salary = 100.0;

        public string GetName()
        {
            return name;
        }

        public double Salary
        {
            get { return salary; }
        }
    }
}
namespace privateTest
{
    class MainClass
    {
        static void Main()
        {
            Employee e = new Employee();

            // The data members are inaccessible (private), so
            // then can't be accessed like this:

            //string n = e.name;
            //double s = e.salary;
            // 'name' is indirectly accessed via method:

            string n = e.GetName();

            // 'salary' is indirectly accessed via property
            double s = e.Salary;

            Console.WriteLine("{0} {1}",n,s);
            Console.ReadLine();
       }
    }
}

MainClass无法直接访问对象的name和salary成员,需要属性或者方法。C#的类有field(字段)和Attribute(属性)。字段用小写,并且是不对外暴露,也就是说是私有或者是保护变量(id)。外部如果要操作(读、写)这些字段,需要通过对外暴露出来的属性(ID)的get(读)、set(写)操作。

internalTest

namespace internalTest
{
    internal class BaseClass
    {
        public static int intM = 0;
    }

    //public class BaseClass
    //{
    //    public static int intM = 0;
    //}
}
namespace Assembly
{
    class TestAccess
    {
        static void Main()
        {
            BaseClass myBase = new BaseClass();  // CS0122
        }
    }
}

不在一个程序集中, “internalTest.BaseClass.BaseClass()”不可访问,因为它受保护级别限制。

使用public

namespace internalTest
{
    public class BaseClass_B
    {
        internal static int intM = 0;
    }
}

 

namespace Assembly
{
    public class TestAccess_B
    {
        static void Main()
        {
            BaseClass_B myBase = new BaseClass_B();  // Ok.

            myBase.intM = 444;    // CS0117
       }
    }
}

会报出错误:无法使用实例引用来访问成员“internalTest.BaseClass_B.intM”;请改用类型名来限定它,因为intM在internalTest中为静态方法。

静态成员也称为共享成员,例如静态属性 静态字段 静态方法;静态成员可以在类的实例之间共享。静态类中只能有静态成员,不能有实例成员,因为静态类不能进行实例化;在非静态类中即可以有静态成员也可以有非静态成员;只要是静态成员 属性 字段 方法,都需要用类名去调用;当类第一次加载的时候(第一次被加载到内存的时候),该类下的所有的静态成员都会被加载,实例成员有多少个对象,就会创建多少个对象;静态成员会被加载到静态存储区,直到程序退出时才会被释放;

修改后代码:

namespace Assembly
{
    public class TestAccess_B
    {
        static void Main()
        {
            BaseClass_B myBase_B = new BaseClass_B();   // Ok.

            BaseClass_B.intM = 444;    
       }
    }
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值