5

Within my projects I often want to have a method (or function if you prefer) that is private, however I also want to access it from ONE other class. Is this a possibility?

To clarify, this method can be accessed from ClassA, its own class but not any other.

Zac Shepherd
  • 93
  • 1
  • 6
  • 2
    If you put both classes into an assembly dedicated to only those two classes, you can use `internal`. But ... you might want to rethink why you need to do this. – ta.speot.is Dec 25 '15 at 09:17
  • What is the rational behind this kind of design? – Hamid Pourjam Dec 25 '15 at 09:26
  • Possible duplicate: http://stackoverflow.com/questions/203616/why-does-c-sharp-not-provide-the-c-style-friend-keyword – Lyubomyr Shaydariv Dec 25 '15 at 09:26
  • Check [friend assemblies](https://msdn.microsoft.com/en-us/library/0tke9fxk.aspx). It might suits your needs. – Hamid Pourjam Dec 25 '15 at 09:26
  • 2
    I'm voting to close this question as off-topic because It's not constructive. – Hamid Pourjam Dec 25 '15 at 09:27
  • 1
    Thankyou all for giving your input it helped a lot and you gave some useful resources. I am aware that it is not necessarily the best architecture but for my purposes it would help a lot. As many of you have suggested, using the intern key word as well as using the same assembly is what I was looking for and I am shocked I can. I would also like to apologise as my emphasis on "ONLY" (No removed) as it was intended for the extra class as well as itself, but I miss wrote it. – Zac Shepherd Dec 25 '15 at 10:39

7 Answers7

2

You can make this method protected, if it suits your OOP structure:

public class A 
{
    protected void Test()
    {
        Console.WriteLine("I can only be called from B");
    }
}

public class B : A
{
    public void Pub()
    {
        Test();
    }
}

And there many other ways to do this.

However, in general, it sounds like a wrong look at access modifiers.
If you want to only call your method from exactly one place, then just call it from exactly one place.
The fact that this method should be called from another class, makes him public, logically and architecturally.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
  • Every class that is derived from `A` can access `Test` method. OP wants "however I also want to access it from ONE other class, and this other class only!" – Hamid Pourjam Dec 25 '15 at 09:30
2

The best way that I can think of is this.

In C# 5, a set of caller information attributes were added, namely [System.Runtime.CompilerServices.CallerMemberName], [System.Runtime.CompilerServices.CallerFilePath], and [System.Runtime.CompilerServices.CallerLineNumber]. We can use the CallerFilePathAttribute to see whether the caller comes from a particular .cs file.

Usually, one file will only contain one class or struct. For example, ClassA is defined in ClassA.cs. You can check if the caller file name matches ClassA.cs in the method.

So modify your method's parameters like this:

([CallerFilePath] string callerFilePath = "" /*Other parameters*/)

In the method, check if the callerFilePath matches the file path of ClassA. If it does not, throw an exception saying that the method can only be accessed from ClassA!

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Yeah... I know. But still, you can't use the method in a class other than `ClassA`. So it meets the requirements! @dotctor – Sweeper Dec 25 '15 at 09:32
2

There are plenty of ways to do this untill your last statement that is "and ONLY that class", i can only think of 1 way to do that and it is to have the classes laid out in assemblies as such as such:

Assembly A only contains class A with the method you want declared as internal

Assembly B declared as a friendly assembly : https://msdn.microsoft.com/en-us/library/0tke9fxk.aspx and contains code to call A (it can as to it it is internal as if in the same assembly as it is a friend assembly)

No other assembly linked to A , B or both will be able to call the method on class A as it is internal.

Ronan Thibaudau
  • 3,413
  • 3
  • 29
  • 78
1

Another simple way to control member access is using delegates. Let's assume you have a private method:

class SecureMethod {
    private void DoSomething() { }
}

You can provide access to this method by injecting delegate to this method:

class ClassA {
 public ClassA(Action secureMethod) { }
}

SecureMethod  objWithSecureMethod;
var a = new ClassA( objWithSecureMethod.DoSomething );
Vitaliy Fedorchenko
  • 8,447
  • 3
  • 37
  • 34
1

I'm showing you how do to this, but these are very bad practices:

public class A
{
    private void CanOnlyCallMethodInClassB();
    public static void SetHandlerCanOnlyCallMethodInClassB(ClassB b)
    {
        b.MethodFromClassA = CanOnlyCallMethodInClassB;
    }
}
public class B
{
    public Action MethodFromClassA { get; set; }
}

in code:

var b = new B();
A.SetHandlerCanOnlyCallMethodInClassB(b);
b.MethodFromClassA();

but better way is to use object of ClassB in method's classA. Search google for strategy pattern or use inheritance.

Marek Woźniak
  • 1,766
  • 16
  • 34
0

Whatever you are asking is not possible in C#. I mean you can not allow only one class to use private method. All you can do is to use internal which allows classes of just one assembly to access your methods or protected which is accessible within its class and by derived class instances!

Apart from that There is not any thumb rule for what you are asking but you can do some hack as shown below:

MethodInfo privateMethod = instance.GetType().GetMethod("NameOfPrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
privateMethod.Invoke(instance, new object[] { methodParameters });
Neel
  • 11,625
  • 3
  • 43
  • 61
0

One slightly dirty trick to use a method from class B in class A is to make the method protected rather than private and derive A from B.

Another possibility, probably better, is to make the method internal rather than private and then put class A and B in the same assembly.

Brian Towers
  • 340
  • 12
  • 15