Why does C# not provide the C++ style 'friend' keyword?

1,594

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#.

Share:
1,594

Related videos on Youtube

user2946171
Author by

user2946171

Updated on April 25, 2020

Comments

  • user2946171
    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
      jpoday over 15 years
      i feel protected internal is a good compromise..
    • Ash
      Ash over 15 years
      It'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
      danswain over 14 years
      I 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
      sellibitze over 14 years
      It'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
      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
      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
      jaybers almost 9 years
      Because Microsoft did not have the philosophy your friends should see your private parts.
    • GrandOpener
      GrandOpener over 8 years
      Don'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
    Ash over 15 years
    Close, 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
    Ash over 15 years
    I 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
    Ash over 15 years
    Good 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
    Ash over 15 years
    So 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
    Parappa over 15 years
    I'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
    Eduardo Scoz over 15 years
    What fundamental attributes are undermined? What relationships are broken? I'd like to understand what you're talking about. Thanks in advance!
  • Stewart Johnson
    Stewart Johnson over 15 years
    I 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
    Nemanja Trifunovic over 15 years
    C# '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.
    Edouard A. over 15 years
    I agree. I never need the friend keyword. It's generally used to solve complex maintenance issues.
  • mmx
    mmx about 15 years
    Anders should be praised for the features he left out not the ones he included.
  • We Are All Monica
    We Are All Monica over 14 years
    Operator overloading, anyone??
  • bashmohandes
    bashmohandes over 14 years
    how many times you found a good case for operator overloading seriously ?
  • Quibblesome
    Quibblesome over 14 years
    You still can use "friend" but you can apply it to assemblies instead allowing different libraries to share internal classes.
  • Quibblesome
    Quibblesome over 14 years
    I 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
    Ali Mst over 14 years
    I 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
    MaddTheSane over 14 years
    ...and the corresponding entry in the FQA: yosefk.com/c++fqa/friend.html#fqa-14.2
  • josesuero
    josesuero over 14 years
    This 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
    Konrad Rudolph over 14 years
    No, that answer is factually wrong, and other threads on SO already explain why, e.g. stackoverflow.com/questions/17434/…
  • Konrad Rudolph
    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
    Max Lybbert over 14 years
    I routinely overload operator(), operator<<, and a few others.
  • John K
    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
    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
    Mark A. Donohoe almost 13 years
    I'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
    Mark A. Donohoe almost 13 years
    The 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
    Edward Robertson over 12 years
    I 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
    Edward Robertson over 12 years
    C# 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
    kaalus over 12 years
    Friend 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
    kaalus over 12 years
    There 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
    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
    kaalus over 12 years
    Unless you are working on a Silverlight application.
  • zumalifeguard
    zumalifeguard over 12 years
    I 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
    CodesInChaos over 12 years
    In 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
    Nawaz over 12 years
    -1. friend is not a bad thing; on the contrary, it is far better than internal. And Nelson's explanation is bad and incorrect.
  • Nawaz
    Nawaz over 12 years
    +1 for "Using friend is not about violating the encapsulation, but on the contrary it's about enforcing it"
  • prabhakaran
    prabhakaran about 12 years
    The 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
    Jesse McGrew over 11 years
    That FriendClass parameter doesn't serve as access control: you can call c.MyMethod((FriendClass) null, 5.5, 3) from any class.
  • SwissCoder
    SwissCoder over 11 years
    good 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
    kaalus over 11 years
    Here'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
    kaalus over 11 years
    Sadly friendship cannot be simulated in any possible way. See this question: stackoverflow.com/questions/5921612/…
  • Grault
    Grault over 11 years
    I'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
    Paul Alexander almost 9 years
    what if you have other views on the screen and you want the dimensions of the mapview only?
  • Quentin Klein
    Quentin Klein almost 9 years
    You 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
    cubuspl42 almost 9 years
    ... and memory is not the only kind of resource. People often act as if it was true.
  • GrandOpener
    GrandOpener over 8 years
    Interfaces 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
    GrandOpener over 8 years
    A 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
    Luc Hermitte over 8 years
    Encapsulation 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
    Hatchling over 7 years
    Exactly. 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
    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
    KthProg about 7 years
    This is an awesome answer that needs more upvotes.
  • Sebastian Mach
    Sebastian Mach over 6 years
    Not 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 or public. 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
    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
    AustinWBryan almost 6 years
    But 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
    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
    Anthony Monterrosa over 4 years
    I'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
    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
    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
    kaalus over 3 years
    This 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
    John Thoits over 3 years
    I 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
    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.