223

Possible Duplicate:
Why does C# not provide the C++ style ‘friend’ keyword?

I'd like the private member variables of a class to be accessible to a Tester class without exposing them to other classes.

In C++ I'd just declare the Tester class as a friend, how do I do this in C#? Can someone give me an example?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Ben L
  • 6,618
  • 8
  • 39
  • 34
  • 3
    You shouldn't test private members directly like if they were accessible as public. Usually, people test against Public members only: http://stackoverflow.com/a/5662371/62921 Private members would be tested along the way indirectly. – ForceMagic Jun 21 '13 at 14:09
  • 5
    This is not a duplicate. The other question is asking why it is missing, not how to get around it. – DanielV Feb 06 '19 at 04:38
  • 1
    For testing - use private accessor - https://stackoverflow.com/a/4052474/828062 For factory pattern - mark the method as `internal` or `protected internal` - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers – zendu May 15 '19 at 02:03
  • 1
    This is not a duplicate. The other question is *"opinion-based"* (which is why some mean-spirited people decided to close that other question). I don't know why unhelpful troglodytes decided to close *this* question - it is neither a duplicate, nor opinion based. – Ian Boyd Nov 14 '21 at 16:23
  • @IanBoyd, "troglodyte" is a bit much. [Be nice](https://stackoverflow.com/conduct), please. – ChrisGPT was on strike Nov 15 '21 at 21:19
  • Of course you should test internal state in unit tests. – Kaitain Jul 22 '22 at 17:05

5 Answers5

299

There's no direct equivalent of "friend" - the closest that's available (and it isn't very close) is InternalsVisibleTo. I've only ever used this attribute for testing - where it's very handy!

Example: To be placed in AssemblyInfo.cs

[assembly: InternalsVisibleTo("OtherAssembly")]
bytecode77
  • 14,163
  • 30
  • 110
  • 141
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 19
    Interesting note, in VB.NET `Internal` is still called `Friend`. – Jeff Oct 17 '13 at 19:55
  • 1
    MSDN says: "All nonpublic types in an assembly are visible to another assembly" How ugly ! Who will ever use that nonsense? I prefer the answer from RobG. – Elmue Jan 22 '14 at 18:52
  • 5
    @Elmue: MSDN is incorrect. Private nested types wouldn't be visible, for example. And the internal members are only visible to the *specified* assembly - it's not like it's just making everything public. I *far* prefer using this over reflection, which isn't refactoring-friendly or compile-time-checking-friendly. – Jon Skeet Jan 22 '14 at 18:53
  • OK. Let's better say that both are ugly workarounds. The original question was an equivalent for friend classes. For me it is very weird that Microsoft did not implement that. I want one class have access to another class in the SAME assembly. What do I do ? – Elmue Jan 25 '14 at 02:39
  • 3
    @Elmue: You make the class internal, that's all. Yes, it's less fine-grained than `friend` - which is useful in some cases, and less useful in others. Personally it doesn't bother me. – Jon Skeet Jan 25 '14 at 08:00
  • Yes I know internal. But if both classes must be public and one must access the variables of the other, the only option would be to make the variables public. Not nice. – Elmue Jan 25 '14 at 13:13
  • @Elmue: I always keep *fields* private anyway... But I'm happy enough to have internal properties. There's no need to make them public. – Jon Skeet Jan 25 '14 at 13:21
  • This is actually very good and also close to friend class in my opinion. I added a short example, if that's ok. – bytecode77 Nov 25 '16 at 18:58
  • If I understand strong-named assemblies correctly, mark your assembly as 'Strong Named' then only other 'strong named' assemblies can *see* the `internal`s. Still, would be nice if there were a `friend` access level but I'm not sure how it would work. – IAbstract Jan 19 '23 at 15:15
  • @IAbstract: No, strong naming is conceptually entirely distinct from `InternalsVisibleTo`. They only interact in that when a strong-named assembly wants to use `InternalsVisibleTo` to grant access to its internals from another assembly, the other assembly must also be strong-named. – Jon Skeet Jan 19 '23 at 15:37
  • @JonSkeet: I mentioned it because MS documentation specifically speaks to strong-naming assemblies in tandem with `InternalsVisibleTo`. – IAbstract Jan 20 '23 at 05:39
  • @IAbstract: The relationship is only as I stated above. Strong-naming makes `InternalsVisibleTo` slightly more constrained, that's all. It's more that you can only refer to other strongly-named assemblies in `InternalsVisibleTo` than anything else - it's not about how that then applies. – Jon Skeet Jan 20 '23 at 07:17
121

The closest equivalent is to create a nested class which will be able to access the outer class' private members. Something like this:

class Outer
{
    class Inner
    {
       // This class can access Outer's private members
    }
}

or if you prefer to put the Inner class in another file:

Outer.cs
partial class Outer
{
}


Inner.cs
partial class Outer
{
    class Inner
    {
       // This class can access Outer's private members
    }
}
IAbstract
  • 19,551
  • 15
  • 98
  • 146
sjp
  • 1,247
  • 1
  • 8
  • 2
  • 11
    Note that in order to access the outer class' members, unless the variable is static (or const), you still need a reference to the instance of Outer. As per the accepted answer here: http://stackoverflow.com/questions/3155172/inner-class-and-outer-class-in-c-sharp – Itison Jan 08 '13 at 02:45
  • I wonder if you could use extension methods for the `Inner` class. I'm going to try it out! :) – Jess May 01 '15 at 12:56
  • 4
    Doh! Extension methods are not allowed on an inner class. – Jess May 01 '15 at 13:25
  • 2
    I find this an extremely interesting idea. If we can except the token "partial" keyword, then we can allow other classes (repository, factory, ...) to obtain access to our private members. What's more, that class is forced to make it blatently obvious that it is doing so (i.e. wrap itself in a partial of the class it is accessing). – Timo Feb 12 '17 at 23:26
  • 1
    this is a correct answer but has wrong explanation. You would use Inner class in the outer class and hide from others, not the other way round. – Code Name Jack Feb 04 '19 at 18:14
  • 1
    This is an old post, however I have a point to add. Totally agree with @CodeNameJack, you would use inner in the outer, however, this way access is not granted, and comiplation error arises when trying to access the variable of inner class. You have access from Inner class to Outer class private variables, but not the other way round (from Outer class to Inner private variables) which turns to be quite weird to me, but as far as I checked this is how it works. – rustyBucketBay May 06 '20 at 07:39
  • I love this approach. To really cement it in at compile time so that external code can't abuse the nested class I declare the public nested class as abstract, and then inherit and implement with a private nested class. This way the outer class has complete control over who can access the nested class. – John Thoits Feb 05 '21 at 22:37
  • 1
    @JohnThoits I don't see the point of your approach, concretely "so that external code can't abuse the nested class" and "This way the outer class has complete control over who can access the nested class", as you would use Inner class in the outer class and hide from others, not the other way round, so unless you have a reference of the inner class in the outer one, any of the member would be accesible. In the case of the outer class having a ref of the inner, the access level is the same one as if the class was not nested. Does your abstract + inherit approach change any of this? – rustyBucketBay Jan 11 '22 at 09:12
  • @rustyBucketBay: I have no idea what you are describing, so I will just clarify. An outer class, class1, wants to expose functionality from the nested class, class1.class2. class1 needs access to members of class2 that other classes should not have. class1.class2 is marked private, with public members accessible to class1, but inherits a public abstract class to implement members exposed outside of class1. class1 has a reference to class1.class2, and returns it as an instance of the abstract class to others. – John Thoits Jan 12 '22 at 21:55
  • 1
    thanks for clarifying @JohnThoits, I think I understand your abstract + inner class ref expose approach. However if you have a reference to the inner class instance, isnt it enough to make a public property in class1 that gets/sets the class2 property to expose? [fiddle](https://dotnetfiddle.net/i5duDd) – rustyBucketBay Jan 12 '22 at 22:48
  • 1
    I left what I understood from your explanation regarding the abstract implementation commented in the fiddle, which achieves the same, exposing the inner class (class2) properties to the "outside" through the outer class instance (class1) – rustyBucketBay Jan 12 '22 at 22:51
  • I see what you're saying @rustyBucketBay. Yes, you're absolutely right, it is enough to expose class2 through class1. The reason I choose to use tricks like this is to change what the statements look like, it's a kind of abuse of the programming language I suppose. Others have called it "fluent programming" (I think calling it that is a little over the top, but we all want to talk-up what we're into.) – John Thoits Jan 14 '22 at 22:04
  • And after commenting with you, I reviewed the question and I realize I forgot the benefit that class2 has access to class1, so it does give an added opportunity to have a second state which is independent of class1 but still has access to the private members of class1. – John Thoits Jan 14 '22 at 22:36
  • Make the `Inner` class *`internal`* ... then use the `InternalsVisibleTo` assembly decorator; and make your assemblies strong-named. – IAbstract Jan 19 '23 at 15:17
48

Take a very common pattern. Class Factory makes Widgets. The Factory class needs to muck about with the internals, because, it is the Factory. Both are implemented in the same file and are, by design and desire and nature, tightly coupled classes -- in fact, Widget is really just an output type from factory.

In C++, make the Factory a friend of Widget class.

In C#, what can we do? The only decent solution that has occurred to me is to invent an interface, IWidget, which only exposes the public methods, and have the Factory return IWidget interfaces.

This involves a fair amount of tedium - exposing all the naturally public properties again in the interface.

Freddy mac
  • 491
  • 4
  • 2
  • 2
    It's a good pattern to use, but not often a good solution when unit testing, because you need fine control over the construction of the class you're testing, which should be isolated from other dependencies. If my factory injected other concrete dependencies into the class I'm testing, I'd be in strife. – andrensairr Oct 09 '19 at 21:58
16

There isn't a 'friend' keyword in C# but one option for testing private methods is to use System.Reflection to get a handle to the method. This will allow you to invoke private methods.

Given a class with this definition:

public class Class1
{
    private int CallMe()
    {
        return 1;
    }
}

You can invoke it using this code:

Class1 c = new Class1();
Type class1Type = c.GetType();
MethodInfo callMeMethod = class1Type.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.NonPublic);

int result = (int)callMeMethod.Invoke(c, null);

Console.WriteLine(result);

If you are using Visual Studio Team System then you can get VS to automatically generate a proxy class with private accessors in it by right clicking the method and selecting "Create Unit Tests..."

RobG
  • 541
  • 2
  • 6
  • 4
    Reflection has heavy performance cost and oftenly leads to poorly readable code. The "partial outer class" approach is much better for me when it's an option. – AFract Jul 13 '17 at 07:38
  • 4
    @AFract - as of .NET 4.5.1, Reflection was re-written and is no longer a performance concern. This used to be the case prior to 4.5.1. Unfortunately, the CLR Team did a poor job of communicating this fact. Try testing some heavy Reflection code compiled pre-4.5.1 and re-test the same exact code under .NET 4.5.1+. You will see a massive difference. – Dave Black Nov 15 '19 at 23:10
7

You can simulate a friend access if the class that is given the right to access is inside another package and if the methods you are exposing are marked as internal or internal protected. You have to modify the assembly you want to share and add the following settings to AssemblyInfo.cs :

// Expose the internal members to the types in the My.Tester assembly
[assembly: InternalsVisibleTo("My.Tester, PublicKey=" +
"012700000480000094000000060200000024000052534131000400000100010091ab9" +
"ba23e07d4fb7404041ec4d81193cfa9d661e0e24bd2c03182e0e7fc75b265a092a3f8" +
"52c672895e55b95611684ea090e787497b0d11b902b1eccd9bc9ea3c9a56740ecda8e" +
"961c93c3960136eefcdf106955a4eb8fff2a97f66049cd0228854b24709c0c945b499" +
"413d29a2801a39d4c4c30bab653ebc8bf604f5840c88")]

The public key is optional, depending on your needs.

tomfanning
  • 9,552
  • 4
  • 50
  • 78
smartmobili
  • 71
  • 1
  • 1