关于C#中类的成员的访问权限的控制范围的讨论

讨论:

在C#中类的成员可以通过private等关键词限制访问权限,众所周知,具有private关键字的属性和方法无法被其它类访问。

例如以下代码:

// 示例1
class A
{
    private int x;
    public int y;
}
class B
{
    public void Func(A a)
    {
        a.x = 1;    // 不通过,无法访问a的私有成员
        a.y = 1;    // 通过,可以访问a的公共成员
    }
}

在B的Func中,只能访问a.y,而不能访问a.x,这是因为private关键字限制了x只能被类A访问

然而 ,注意我说的是,只能被类A访问,而不是只能被类A的实例a访问,来看以下例子:

// 示例2
class A
{
    private int x;
    public int y;

    public void Func(A a)
    {
        a.x = this.x;   // 通过
        a.y = this.y;   // 通过
    }
}

在这个例子中,同样是通过a.x,对类A的a实例的私有成员x进行了访问(有点拗口),但是却能编译通过的。

这一点让人感到奇怪,因为通常来说,如果x是某个类的私有属性,我们一般不会写下类似a.x的访问语句,因为这通常是不通过的,然而在示例2中,这种访问却是符合语法的,起码编译器是不会报错的。

这似乎说明了一个特性,那就是在C#中,类A的a实例可以访问类A的b实例的私有成员

结论

经过多种试验,查阅相关资料,验证了这个特性:C#的访问权限设计,是基于类的,而不是基于实例的。一个类的实例可以访问该类的任何其他实例的私有成员。

这种特性看起来有一点破坏了面向对象的封装性,在设计时容易产生一些意外,比如在涉及到派生类的时候。

不过这种特性也使得C#在实现某些功能时提供更大的灵活性,比如复制构造函数、比较函数等,它们需要访问另一个实例的私有数据。

作为开发者在使用这种权限时需要谨慎,在设计面向对象系统时避免破坏封装性。

其他语言

C++

我在C++上进行了测试,发现C++也具有相同的特性,在以下例子中,FuncA可以访问a.x,而FuncB无法访问a.x:

class A
{
private:
    int x = 1;
public:
    void FuncA(A a)
    {
        a.x = 2;
    }
};
class B
{
public:
    void FuncB(A a)
    {
        a.x = 2;
    }
};

JAVA

我对JAVA了解得不多,曾经与同事讨论发现,JAVA与C#在语法上至少有80%的相似度,一些简单的代码甚至只要换个壳子就可以互相运行。但是与同事就访问控制的特性讨论后发现,JAVA对于访问权限的控制却是更加严格,在Java中,一个类的实例无法访问另一个实例的私有成员,访问权限是基于实例的。这一点与C#便有区别

后记

关于C#的访问控制,我也是偶然才发现它基于类而不是基于实例这一特性的,这在后续的程序设计中是值得注意的一点,因此写下这篇文章以作记录。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值