Why does C# not provide the C++ style 'friend' keyword?
Solution 1
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 ;))
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.
EDIT Let me clarify how the friend keyword undermines 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.
Solution 2
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 message in the other thread, or if you prefer see the relevant entry in the C++ FAQ.
Solution 3
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.
Solution 4
In fact, C# gives possibility to get same behavior in pure OOP way without special words - it's private interfaces.
As far as question What is the C# equivalent of friend? was marked as duplicate to this article and no one there propose really good realization - I will show answer on both question here.
Main idea was taking from here: What is a private interface?
Let's say, we need some class which could manage instances of another classes and call some special methods on them. We don't want to give possibility to call this methods to any other classes. This is exactly same thing what friend c++ keyword do in c++ world.
I think good example in real practice could be Full State Machine pattern where some controller update current state object and switch to another state object when necessary.
You could:
- The easiest and worst way to make Update() method public - hope everyone understand why it's bad.
- Next way is to mark it as internal. It's good enough if you put your classes to another assembly but even then each class in that assembly could call each internal method.
- Use private/protected interface - and I followed this way.
Controller.cs
public class Controller
{
private interface IState
{
void Update();
}
public class StateBase : IState
{
void IState.Update() { }
}
public Controller()
{
//it's only way call Update is to cast obj to IState
IState obj = new StateBase();
obj.Update();
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
//it's impossible to write Controller.IState p = new Controller.StateBase();
//Controller.IState is hidden
var p = new Controller.StateBase();
//p.Update(); //is not accessible
}
}
Well, what about inheritance?
We need to use technique described in Since explicit interface member implementations cannot be declared virtual and mark IState as protected to give possibility to derive from Controller too.
Controller.cs
public class Controller
{
protected interface IState
{
void Update();
}
public class StateBase : IState
{
void IState.Update() { OnUpdate(); }
protected virtual void OnUpdate()
{
Console.WriteLine("StateBase.OnUpdate()");
}
}
public Controller()
{
IState obj = new PlayerIdleState();
obj.Update();
}
}
PlayerIdleState.cs
public class PlayerIdleState: Controller.StateBase
{
protected override void OnUpdate()
{
base.OnUpdate();
Console.WriteLine("PlayerIdleState.OnUpdate()");
}
}
And finally example how to test class Controller throw inheritance: ControllerTest.cs
class ControllerTest: Controller
{
public ControllerTest()
{
IState testObj = new PlayerIdleState();
testObj.Update();
}
}
Hope I cover all cases and my answer was useful.
Solution 5
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.
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#.
Related videos on Youtube
user2946171
Updated on April 25, 2020Comments
-
user2946171 about 4 years
I'm trying to get width and height from a map fragment. However methods getWidth and getHeight are deprecated and i dont now how to do in google v2.
I used to do like this way:
display = getWindowManager().getDefaultDisplay(); width = display.getWidth(); height = display.getHeight();
Please someone help
-
jpoday over 15 yearsi feel protected internal is a good compromise..
-
Ash over 15 yearsIt's not too confusing is it? As I said above the GOF book uses it quite often in examples. To me it's no more confusing then internal.
-
danswain over 14 yearsI can certainly see scenarios where they can be very useful, as already mentioned Unit Testing. But do you really want your friends accessing your privates?
-
sellibitze over 14 yearsIt's easy to answer: C# offers "internal" as access modifier which grants access to the all the code in the same module/assembly. This removes the need for something like friend. In Java the keyword "protected" behaves similarly w.r.t. access from the same package.
-
Ash over 14 years@sellibitze, I mention the differences with internal in the question. The problem with Interanl is that all classes in the assembly can access the internal members. This breaks encapsulation as maany of these classes may not need access.
-
stakx - no longer contributing over 11 years"why this was left out of C#" -- By saying that, the OP implicitly compares C# to C++. But why should C++ be the measuring tape for C#? Why should C# have to be anything like C++? It could be... but it simply isn't.
-
jaybers almost 9 yearsBecause Microsoft did not have the philosophy your friends should see your private parts.
-
GrandOpener over 8 yearsDon't be so quick to dismiss
internal
. My experience is that the friend relationship is usually between two closely related classes (list and node, factory and widget, etc.) that are convenient to split into a separate assembly. Maybe it's a little weird that your two lists might have access to each other's nodes, but it's not like you have to make those properties or methods available to external/client code. This is a little weird for people who are used to writing single monolithic projects, but there are actually a lot of benefits of separating assemblies.
-
-
Ash over 15 yearsClose, but not quite there. I suppose it depends on how you structure your assemblies/classes, but it would be more elegant to minimise the number of classes given access using friend. FOr example in a utility/helper assembly, not all classes should have access to internal members.
-
Ash over 15 yearsI think the compiler could support it reasonably easily at least between classes within an assembly. Just a matter of relaxing access checking for the friend class on the target class. Friend between classes in external assemblies may need more fundamental changes to the CLR perhaps.
-
Ash over 15 yearsGood point. Did you have a chance to look at the earlier SO question (asked by monoxide and linked above?. I'd be interested in how best to solve that in C#?
-
Ash over 15 yearsSo it seems that the reason the 'internal' keyword is in C# but 'friend' is not, is that internal is more explicit then friend. I guess as soon as you see internal, you know immediately it's possible that another class could access them.
-
Parappa over 15 yearsI'm not sure exactly how to do it in C#, but I think Jon Skeet's answer to monoxide's question points in the right direction. C# allows nested classes. I haven't actually tried to code out and compile a solution, though. :)
-
Eduardo Scoz over 15 yearsWhat fundamental attributes are undermined? What relationships are broken? I'd like to understand what you're talking about. Thanks in advance!
-
Stewart Johnson over 15 yearsI don't think friend was left out for "OO purity". I think it's more likely because the C# is translated to IL when you compile, and the other types you may want to friend are available. It's the same way C++ generics are entirely compile-time, and C#'s aren't.
-
Nemanja Trifunovic over 15 yearsC# 'internal' is actually hurting encapsulation much more than C++ 'friend'. With "friendship", the owner explicitely gives the permission to whoever it wants. "Internal" is an open ended concept.
-
Edouard A. over 15 yearsI agree. I never need the friend keyword. It's generally used to solve complex maintenance issues.
-
mmx about 15 yearsAnders should be praised for the features he left out not the ones he included.
-
We Are All Monica over 14 yearsOperator overloading, anyone??
-
bashmohandes over 14 yearshow many times you found a good case for operator overloading seriously ?
-
Quibblesome over 14 yearsYou still can use "friend" but you can apply it to assemblies instead allowing different libraries to share internal classes.
-
Quibblesome over 14 yearsI disagree that C#'s internal hurts incapsulation though. The opposite in my opinion. You can use it to create an encapsulated ecosystem within an assembly. A number of objects can share internal types within this ecosystem that are not exposed to the rest of the application. I use the "friend" assembly tricks to create unit test assemblies for these objects.
-
Ali Mst over 14 yearsI feel that the mediator pattern is a good example of where friend would be nice. I refactor my Forms to have a mediator. I want my form to be able to call the "event" like methods in the mediator, but I don't really want other classes calling those "event" like methods. The "Friend" feature would give the form access to the methods with out opening it up to everything else in the assembly.
-
MaddTheSane over 14 years...and the corresponding entry in the FQA: yosefk.com/c++fqa/friend.html#fqa-14.2
-
josesuero over 14 yearsThis doesn't make sense.
friend
doesn't let arbitrary classes or functions access private members. It lets the specific functions or classes that were marked as friend do so. The class owning the private member still controls access to it 100%. You might as well argue that public member methods. Both ensure that the methods specifically listed in the class are given access to private members of the class. -
Konrad Rudolph over 14 yearsNo, that answer is factually wrong, and other threads on SO already explain why, e.g. stackoverflow.com/questions/17434/…
-
Konrad Rudolph over 14 years@Ash: You need to get used to it but once you see assemblies as the fundamental building block of your applications,
internal
makes a great deal more sense and provides an excellent trade-off between encapsulation and utility. Java’s default access is even better, though. -
Max Lybbert over 14 yearsI routinely overload operator(), operator<<, and a few others.
-
John K over 14 years@Konrad: The link you provided talks specifically to encapsulation whereas @NelsonLaQuet generalizes OOP in regard to
friend
. Although your link might be correct in and of itself, comparing it to this answer feels like comparing apples and oranges, or at least red apples and green apples. -
Powerlord over 14 years@Nemanja Trifunovic: '"Internal" is an open ended concept.' Not really. Since you the programmer control what classes are in your assemblies, you implicitly control which classes can access it. However, it's a bad idea to let classes have direct access to your stuff anyway, which is why .NET introduced the properties syntax.
-
Mark A. Donohoe almost 13 yearsI'll give you a very simple case that completely debunks your 'design issue' comment. Parent-Child. A parent owns its children. A child in the parent's 'Children' collection is owned by that parent. The Parent property's setter on Child shouldn't be settable by just anyone. It needs to be assigned when and only when the child is added to the parent's Children collection. tIf it's public, anyone can change it. Internal: anyone in that assembly. Private? No one. Making the setter a friend to parent eliminates those cases and still keeps your classes separate, but tightly related. Huzzah!!
-
Mark A. Donohoe almost 13 yearsThe problem with the interface approach of replacing 'Friend' is for an object to expose an interface, that means anyone can cast the object to that interface and have access to the methods! Scoping the interface to internal, protected or private doesn't work either as if that worked, you could just scope the method in question! Think about a mother and child in a shopping mall. Public is everyone in the world. Internal is just the people in the mall. Private is just the mother or the child. 'Friend' is something between the mother and daughter only.
-
Edward Robertson over 12 yearsI was going to make a comment about "friend" being useful for factory classes, but I'm glad to see that someone has already made it.
-
Edward Robertson over 12 yearsC# is missing deterministic destruction because it's slower than garbage collection. Deterministic destruction takes time for every object created, whereas garbage collection only takes time for the currently live objects. In most cases, this is faster, and the more short-lived objects there are in the system, the relatively faster garbage collection gets.
-
kaalus over 12 yearsFriend is required to implement some most basic design patterns. Generally, it is needed when more than one class needs to work together, like in e.g. manager/managed pattern. Lack of friend makes me often use hacks like making privates public.
-
kaalus over 12 yearsThere are a lot of such cases, such as most basic manager/managed pattern. There is another question on SO and no one figured a way how to do it without a friend. Not sure what makes people think that one class "will always suffice". Sometimes more than one class needs to work together.
-
kaalus over 12 years@Edward Robertson Deterministic destruction does not take any time unless there is a destructor defined. But in this case, garbage collection is much worse, because then you need to use a finalizer, which is slower and nondeterministic.
-
kaalus over 12 yearsUnless you are working on a Silverlight application.
-
zumalifeguard over 12 yearsI think quite the opposite. If an assembly has 50 classes, if 3 of those classes use some utility class, then today, your only option is to mark that utility class as "internal". In doing so, you not only make it available for use to the 3 classes, but to the rest of the classes in the assembly. What if all you wanted to do is provide finer-grained access such that only the three classes in question had access to the utility class. It actually makes it more object oriented because it improves encapsulation.
-
CodesInChaos over 12 yearsIn C# you can overload most operators. You can't overload assignment operators, but on the other hand you can override
||
/&&
while keeping them short circuiting. Default parameters were added in C# 4. -
Nawaz over 12 years-1.
friend
is not a bad thing; on the contrary, it is far better thaninternal
. And Nelson's explanation is bad and incorrect. -
Nawaz over 12 years+1 for "Using friend is not about violating the encapsulation, but on the contrary it's about enforcing it"
-
prabhakaran about 12 yearsThe situation described by "Marquel"is the perfect example for the need of friend. This will be the only choice if the parent has list of childs,the list should be in some order and every child should have their appropriate list index . Then obviously the parent should do everything of that child.
-
Jesse McGrew over 11 yearsThat FriendClass parameter doesn't serve as access control: you can call
c.MyMethod((FriendClass) null, 5.5, 3)
from any class. -
SwissCoder over 11 yearsgood hint, as probably often people looking for friend want to find a way to unit test with the ability to have more internal 'knowledge'.
-
kaalus over 11 yearsHere's one: stackoverflow.com/questions/5921612/… As I come from C++ background, lack of friend drives me insane almost daily. In my few years with C# I have made literally hundreds of methods public where they could be private and safer instead, all because of lack of friend. Personally I think friend is the most important thing that should be added to .NET
-
kaalus over 11 yearsSadly friendship cannot be simulated in any possible way. See this question: stackoverflow.com/questions/5921612/…
-
Grault over 11 yearsI'm not an OOP sentinel, but it looks like it solves everyone's gripes against friend and internal. But I would suggest using an attribute to avoid the extension of C#'s syntax: [PublicFor Bar] void addBar(Bar bar) { } ... Not that I'm sure that makes sense; I don't know how attributes work or whether they can fiddle with accessibility (they do a lot of other "magical" stuff).
-
Paul Alexander almost 9 yearswhat if you have other views on the screen and you want the dimensions of the mapview only?
-
Quentin Klein almost 9 yearsYou should be able to do that with a
ViewTreeObserver
like explained in this post stackoverflow.com/questions/3779173/…. The goal is to compute the size at runtime and observe the view you want to get its size. -
cubuspl42 almost 9 years... and memory is not the only kind of resource. People often act as if it was true.
-
GrandOpener over 8 yearsInterfaces do this well. Well structured code should protect against accidental misuse, not against intentional malice. If you strictly hand out one interface externally, and the user reads your code and steals away a interface documented as for internal use, that's not a flaw in your code, that's someone intentionally being a jerkface. No matter what you do, someone could always use unsafe code to play with the bits regardless. You job in writing code is making something that's hard to use incorrectly. It's impossible to make something that is impossible to use incorrectly.
-
GrandOpener over 8 yearsA matter of semantic opinion I think; and perhaps related to the exact situation in question. Making a class a
friend
gives it access to ALL of your private members, even if you only need to let it set one of them. There is a strong argument to be made that making fields available to another class that doesn't need them counts as "violating encapsulation." There are places in C++ where it is necessary (overloading operators), but there is an encapsulation tradeoff that needs to be carefully considered. It seems the C# designers felt that tradeoff was not worth it. -
Luc Hermitte over 8 yearsEncapsulation is about enforcing invariants. When we define a class as friend to another, we say explicitly that the two classes are strongly tied regarding the management of the invariants of the first one. Having the class made friend is still better than exposing all attributes directly (as public field) or through setters.
-
Hatchling over 7 yearsExactly. When you want to use friend but can't, you're forced to use internal or public, which are much more open to being poked at by things that shouldn't. Especially in a team environment.
-
paul23 over 7 years"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." - this is not an argument why it undermines OOP. Python has no need for privacy at all: rather it depends on an accepted naming scheme to describe what can be easily accessed an what cannot. Yet it is very much an OOP language.
-
KthProg about 7 yearsThis is an awesome answer that needs more upvotes.
-
Sebastian Mach over 6 yearsNot sure how serious your kidding about C++' "pseudo OO" and C#' "pure OO" is, but what's for sure is that object orientedness does in no way imply classes, especially not member functions, and super extremespecially not access modifiesr like
private
orpublic
. Classes and restricted members are just one method to implement OOP. Classic, related read on C++ regarding members and non-members: How non member functions improve encapsulation -
Damian Yerrick almost 6 years"it is rare that you will be distributing your code to 3rd party developers not though a DLL" How true does this remain ten years later with the rise of libraries distributed as free software and maintained on Microsoft GitHub?
-
AustinWBryan almost 6 yearsBut sometimes, I've come across that I need this one member to be private, except for one class. I would like to do a friend class, but instead I have to give some public scope access, either make the member public, or if it's a field or property, make some public handler for it. How does making something that should be private, public better than making it public to only one class?
-
Steve Land over 5 years@max_cn This is a really nice solution, but I cant see a way to get this working with mocking frameworks for unit testing. Any suggestions?
-
Anthony Monterrosa over 4 yearsI'm a bit confused. If I wanted an external class to be able to call Update in your first example (private interface), how would I modify Controller to allow that to happen?
-
max_cn about 4 years@Steve Land, you can use inheritance as in ControllerTest.cs was shown. Add any necessary public methods in a derived test class and you will have access for all protected staff you have in base class.
-
max_cn about 4 years@AnthonyMonterrosa, we are hiding Update from ALL external resources so why you want to share it with someone ;)? Sure you can add some public method to access private members but it will be like a backdoor for any other classes. Anyway, if you need it for testing purposes - use inheritance to make something like ControllerTest class to make any testing cases there.
-
kaalus over 3 yearsThis is a massively verbose and convoluted way to achieve an inferior effect of what "friend" provides (one can still cast to interface and call any functions they want). Lack of friend in C# is biting me almost daily in my everyday work. "Pure OOP" arguments are simply wrong: sometimes two classes need to have a private shared state. Friend provides for that. "Pure OOP" does not.
-
John Thoits over 3 yearsI think a good thing for any C++ programmer to keep in mind is that once two classes are friends, they really aren't truly two separate classes anymore, they've become one class implemented in two parts (though each part can exist without the other). They're pretty much the same thing as "partial" classes in C#.
-
Daniel Bauer about 2 years@kaalus All other classes, except the Controller class in this case, don't know about this private/protected interface so they can't cast to it. Also this solution has advantages over a friend declaration: You can open a specific part on the class to the private interface, so your "friend" class can only use the specific part of it. This will then also be documented in the interface definition.