为什么 C# 不提供 C++ 风格的“朋友”关键字?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/203616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does C# not provide the C++ style 'friend' keyword?
提问by Ash
The C++ friend keywordallows a class A
to designate class B
as its friend. This allows Class B
to access the private
/protected
members of class A
.
在C ++朋友关键字允许class A
指定class B
作为其朋友。这允许Class B
访问private
/protected
的成员class A
。
I've never read anything as to why this was left out of C# (and VB.NET). Most answers to this earlier StackOverflow questionseem to be saying it is a useful part of C++ and there are good reasons to use it. In my experience I'd have to agree.
我从来没有读过任何关于为什么它被排除在 C#(和 VB.NET)之外的信息。这个早期 StackOverflow 问题的大多数答案似乎都在说它是 C++ 的一个有用部分,并且有充分的理由使用它。根据我的经验,我不得不同意。
Another questionseems to me to be really asking how to do something similar to friend
in a C# application. While the answers generally revolve around nested classes, it doesn't seem quite as elegant as using the friend
keyword.
在我看来,另一个问题实际上是在询问如何friend
在 C# 应用程序中执行类似的操作。虽然答案通常围绕嵌套类展开,但它似乎并不像使用friend
关键字那样优雅。
The original Design Patterns bookuses it regularly throughout its examples.
最初的《设计模式》一书在其示例中经常使用它。
So in summary, why is friend
missing from C#, and what is the "best practice" way (or ways) of simulating it in C#?
总而言之,为什么friend
C# 中缺少,以及在 C# 中模拟它的“最佳实践”方式(或方式)是什么?
(By the way, the internal
keyword is notthe same thing, it allows allclasses within the entire assembly to access internal
members, while friend
allows you to give a certain class complete accessto exactly oneother class)
(顺便说一句,该internal
关键字不一样的东西,它可以让所有的整个内部的阶级装配访问internal
成员,同时friend
允许你给某一类的完全访问权限,以正好一个其他类)
采纳答案by Parappa
Having friends in programming is more-or-less considered "dirty" and easy to abuse. It breaks the relationships between classes and undermines some fundamental attributes of an OO language.
在编程方面有朋友或多或少被认为是“肮脏的”并且容易被滥用。它打破了类之间的关系并破坏了面向对象语言的一些基本属性。
That being said, it is a nice feature and I've used it plenty of times myself in C++; and would like to use it in C# too. But I bet because of C#'s "pure" OOness (compared to C++'s pseudo OOness) MS decided that because Java has no friend keyword C# shouldn't either (just kidding ;))
话虽如此,这是一个很好的功能,我自己在 C++ 中使用过很多次;并且也想在 C# 中使用它。但我敢打赌,因为 C# 的“纯”OOness(与 C++ 的伪 OOness 相比),MS 决定因为 Java 没有朋友关键字 C# 也不应该(开玩笑;))
On a serious note: internal is not as good as friend but it does get the job done. Remember that it is rare that you will be distributing your code to 3rd party developers not through a DLL; so as long as you and your team know about the internal classes and their use you should be fine.
严肃地说:内部不如朋友,但它确实可以完成工作。请记住,您很少会不通过 DLL 将代码分发给 3rd 方开发人员;所以只要你和你的团队了解内部类及其使用,你应该没问题。
EDITLet me clarify how the friend keyword undermines OOP.
编辑让我澄清朋友关键字如何破坏 OOP。
Private and protected variables and methods are perhaps one of the most important part of OOP. The idea that objects can hold data or logic that only they can use allows you to write your implementation of functionality independent of your environment - and that your environment cannot alter state information that it is not suited to handle. By using friend you are coupling two classes' implementations together - which is much worse then if you just coupled their interface.
私有和受保护的变量和方法可能是 OOP 中最重要的部分之一。对象可以保存只有它们可以使用的数据或逻辑的想法允许您编写独立于您的环境的功能实现 - 并且您的环境不能改变它不适合处理的状态信息。通过使用friend,您将两个类的实现耦合在一起 - 如果您只是耦合它们的接口,情况会更糟。
回答by jeffm
You can get close to C++ "friend" with the C# keyword "internal".
您可以使用 C# 关键字"internal"来接近 C++ "friend "。
回答by Stewart Johnson
I suspect it has something to do with the C# compilation model -- building IL the JIT compiling that at runtime. i.e.: the same reason that C# generics are fundamentally different to C++ generics.
我怀疑它与 C# 编译模型有关——构建 IL 并在运行时编译 JIT。即:同样的原因,C# 泛型与 C++ 泛型根本不同。
回答by Parappa
You should be able to accomplish the same sorts of things that "friend" is used for in C++ by using interfaces in C#. It requires you to explicitly define which members are being passed between the two classes, which is extra work but may also make the code easier to understand.
通过使用 C# 中的接口,您应该能够完成与 C++ 中使用的“朋友”相同的类型的事情。它要求您明确定义在两个类之间传递哪些成员,这是额外的工作,但也可能使代码更易于理解。
If somebody has an example of a reasonable use of "friend" that cannot be simulated using interfaces, please share it! I'd like to better understand the differences between C++ and C#.
如果有人有不能用接口模拟的合理使用“朋友”的例子,请分享!我想更好地理解 C++ 和 C# 之间的区别。
回答by bashmohandes
If you are working with C++ and you find your self using friend keyword, it is a very strong indication, that you have a design issue, because why the heck a class needs to access the private members of other class??
如果您正在使用 C++ 并且发现自己使用了friend 关键字,这是一个非常强烈的迹象,表明您存在设计问题,因为为什么一个类需要访问其他类的私有成员?
回答by Marc Gravell
For info, another related-but-not-quite-the-same thing in .NET is [InternalsVisibleTo]
, which lets an assembly designate another assembly (such as a unit test assembly) that (effectively) has "internal" access to types/members in the original assembly.
有关信息,.NET 中另一个相关但不完全相同的事情是[InternalsVisibleTo]
,它允许程序集指定另一个程序集(例如单元测试程序集),该程序集(实际上)具有对类型/成员的“内部”访问权限原始组件。
回答by JaredPar
This is actually not an issue with C#. It's a fundamental limitation in IL. C# is limited by this, as is any other .Net language that seeks to be verifiable. This limitation also includes managed classes defined in C++/CLI (Spec section 20.5).
这实际上不是 C# 的问题。这是 IL 中的一个基本限制。C# 受此限制,任何其他寻求可验证的 .Net 语言也受此限制。此限制还包括在 C++/CLI(规范第 20.5 节)中定义的托管类。
That being said I think that Nelson has a good explanation as to why this is a bad thing.
话虽如此,我认为纳尔逊对为什么这是一件坏事有一个很好的解释。
回答by Luc Hermitte
On a side note. Using friend is not about violating the encapsulation, but on the contrary it's about enforcing it. Like accessors+mutators, operators overloading, public inheritance, downcasting, etc., it's often misused, but it does not mean the keyword has no, or worse, a bad purpose.
在旁注。使用朋友不是违反封装,相反,它是强制执行。像访问器+修改器、运算符重载、公共继承、向下转换等,它经常被误用,但这并不意味着关键字没有,或者更糟的是,它没有任何用途。
See Konrad Rudolph's messagein the other thread, or if you prefer see the relevant entryin the C++ FAQ.
请参阅另一个线程中Konrad Rudolph的消息,或者如果您愿意,请参阅C++ FAQ 中的相关条目。
回答by Andy Dent
Friend is extremely useful when writing unit test.
Friend 在编写单元测试时非常有用。
Whilst that comes at a cost of polluting your class declaration slightly, it's also a compiler-enforced reminder of what tests actually might care about the internal state of the class.
虽然这样做的代价是稍微污染了您的类声明,但它也是编译器强制提醒哪些测试实际上可能关心类的内部状态。
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.
我发现一个非常有用和干净的习惯用法是当我有工厂类时,让它们成为他们创建的具有受保护构造函数的项目的朋友。更具体地说,当时我有一个工厂负责为报表编写器对象创建匹配的渲染对象,渲染到给定的环境。在这种情况下,您对报表编写器类(如图片块、布局带、页眉等)与其匹配的呈现对象之间的关系有一个单一的了解。
回答by Matthew
C# is missing the "friend" keyword for the same reason its missing deterministic destruction. Changing conventions makes people feel smart, as if their new ways are superior to someone else' old ways. It's all about pride.
C# 缺少“朋友”关键字的原因与它缺少确定性破坏的原因相同。改变惯例让人们觉得自己很聪明,就好像他们的新方法优于别人的旧方法。这一切都与骄傲有关。
Saying that "friend classes are bad" is as short-sighted as other unqualified statements like "don't use gotos" or "Linux is better than Windows".
说“朋友类不好”与“不要使用 goto”或“Linux 比 Windows 好”等其他不合格的陈述一样短视。
The "friend" keyword combined with a proxy class is a great way to only expose certainparts of a class to specific other class(es). A proxy class can act as a trusted barrier against all other classes. "public" doesn't allow any such targeting, and using "protected" to get the effect with inheritance is awkward if there really is no conceptual "is a" relationship.
“friend”关键字与代理类相结合,是将类的某些部分仅公开给特定的其他类的好方法。代理类可以充当所有其他类的可信屏障。“public”不允许任何这样的目标,如果真的没有概念上的“is a”关系,使用“protected”来获得继承的效果是很尴尬的。