c++的friend关键字允许类a将类B指定为它的friend。这允许类B访问类A的私有/受保护成员。

我从来没有读过任何关于为什么c#(和VB.NET)中不包含这个的东西。大多数关于StackOverflow问题的答案似乎都在说它是c++的一个有用的部分,并且有很好的理由使用它。以我的经验,我不得不同意。

对我来说,另一个问题似乎是在问如何在c#应用程序中做类似于friend的事情。虽然答案通常围绕嵌套类,但它似乎没有使用friend关键字那么优雅。

最初的《设计模式》一书在其示例中经常使用它。

总之,为什么在c#中没有friend,在c#中模拟friend的“最佳实践”方法是什么?

(顺便说一下,internal关键字不是一回事,它允许整个程序集中的所有类访问内部成员,而friend允许你给某个类完全访问另一个类)


当前回答

B.s.d。

有人说,朋友伤害纯粹的孤独。我同意这一点。

还有人说,朋友会帮助封装,我也同意这一点。

我认为友谊应该添加到OO方法中,但不像在c++中那样。我想有一些字段/方法,我的朋友类可以访问,但我不希望他们访问我所有的字段/方法。在现实生活中,我会让我的朋友们进入我的私人冰箱,但我不会让他们进入我的银行账户。

我们可以按照下面的方法实现它

    class C1
    {
        private void MyMethod(double x, int i)
        {
            // some code
        }
        // the friend class would be able to call myMethod
        public void MyMethod(FriendClass F, double x, int i)
        {
            this.MyMethod(x, i);
        }
        //my friend class wouldn't have access to this method 
        private void MyVeryPrivateMethod(string s)
        {
            // some code
        }
    }
    class FriendClass
    {
        public void SomeMethod()
        {
            C1 c = new C1();
            c.MyMethod(this, 5.5, 3);
        }
    }

这当然会生成一个编译器警告,并将损害智能感知。但它会起作用的。

另一方面,我认为一个自信的程序员应该在不访问私有成员的情况下进行测试单元。这已经超出了本文的范围,但请尝试阅读TDD。 然而,如果你仍然想这样做(有c++喜欢的朋友),尝试一些像

#if UNIT_TESTING
        public
#else
        private
#endif
            double x;

所以你写的所有代码都没有定义UNIT_TESTING,当你想要进行单元测试时,你在文件的第一行添加#define UNIT_TESTING(并在#if UNIT_TESTING下编写所有进行单元测试的代码)。这应该小心处理。

因为我认为单元测试对于朋友的使用是一个不好的例子,所以我想举一个例子来说明为什么我认为朋友可以是好的。假设你有一个破碎的系统(类)。随着使用,破碎系统磨损,需要翻新。现在,你希望只有有执照的技工才能修理它。为了让这个例子不那么琐碎,我想说机械师会用他的私人螺丝刀来修理它。这就是为什么机制类应该是breakingSystem类的朋友。

其他回答

B.s.d。

有人说,朋友伤害纯粹的孤独。我同意这一点。

还有人说,朋友会帮助封装,我也同意这一点。

我认为友谊应该添加到OO方法中,但不像在c++中那样。我想有一些字段/方法,我的朋友类可以访问,但我不希望他们访问我所有的字段/方法。在现实生活中,我会让我的朋友们进入我的私人冰箱,但我不会让他们进入我的银行账户。

我们可以按照下面的方法实现它

    class C1
    {
        private void MyMethod(double x, int i)
        {
            // some code
        }
        // the friend class would be able to call myMethod
        public void MyMethod(FriendClass F, double x, int i)
        {
            this.MyMethod(x, i);
        }
        //my friend class wouldn't have access to this method 
        private void MyVeryPrivateMethod(string s)
        {
            // some code
        }
    }
    class FriendClass
    {
        public void SomeMethod()
        {
            C1 c = new C1();
            c.MyMethod(this, 5.5, 3);
        }
    }

这当然会生成一个编译器警告,并将损害智能感知。但它会起作用的。

另一方面,我认为一个自信的程序员应该在不访问私有成员的情况下进行测试单元。这已经超出了本文的范围,但请尝试阅读TDD。 然而,如果你仍然想这样做(有c++喜欢的朋友),尝试一些像

#if UNIT_TESTING
        public
#else
        private
#endif
            double x;

所以你写的所有代码都没有定义UNIT_TESTING,当你想要进行单元测试时,你在文件的第一行添加#define UNIT_TESTING(并在#if UNIT_TESTING下编写所有进行单元测试的代码)。这应该小心处理。

因为我认为单元测试对于朋友的使用是一个不好的例子,所以我想举一个例子来说明为什么我认为朋友可以是好的。假设你有一个破碎的系统(类)。随着使用,破碎系统磨损,需要翻新。现在,你希望只有有执照的技工才能修理它。为了让这个例子不那么琐碎,我想说机械师会用他的私人螺丝刀来修理它。这就是为什么机制类应该是breakingSystem类的朋友。

我读过许多关于“朋友”关键字的聪明评论,我同意它是有用的东西,但我认为“内部”关键字没有那么有用,而且它们对纯OO编程来说都很糟糕。

我们有什么?(说到“朋友”,我也说到“内部”)

使用“friend”是否会使代码对于oo不那么纯粹? 是的, 不使用“friend”会使代码更好吗? 不,我们仍然需要在类之间建立一些私人关系,而且只有打破了我们美丽的封装才能做到,所以这也不好,我可以说它比使用“朋友”更邪恶。

使用friend会产生一些局部问题,不使用friend会给代码库用户带来问题。

在我看来,编程语言的通用解决方案是这样的:

// c++ style
class Foo {
  public_for Bar:
    void addBar(Bar *bar) { }
  public:
  private:
  protected:
};

// c#
class Foo {
    public_for Bar void addBar(Bar bar) { }
}

你觉得怎么样?我认为这是最常见的纯面向对象的解决方案。你可以对你想要的任何类打开任何方法的访问。

Friend在编写单元测试时非常有用。

虽然这是以稍微污染类声明为代价的,但它也是一个编译器强制的提醒,提醒您测试实际上可能关心类的内部状态。

A very useful and clean idiom I've found is when I have factory classes, making them friends of the items they create which have a protected constructor. More specifically, this was when I had a single factory responsible for creating matching rendering objects for report writer objects, rendering to a given environment. In this case you have a single point of knowledge about the relationship between the report-writer classes (things like picture blocks, layout bands, page headers etc.) and their matching rendering objects.

顺便说一句。 使用friend并不是违反封装,相反,它是加强封装。就像访问器+突变器、操作符重载、公共继承、向下强制转换等一样,它经常被误用,但这并不意味着关键字没有,或者更糟,没有一个坏的目的。

请参阅Konrad Rudolph在另一个线程中的消息,或者如果您愿意,请参阅c++常见问题解答中的相关条目。

关于信息,. net中另一个相关但不完全相同的东西是[InternalsVisibleTo],它允许一个程序集指定另一个程序集(例如单元测试程序集),该程序集(有效地)具有对原始程序集中的类型/成员的“内部”访问。