tags:

views:

573

answers:

12

In c# is it possible to create a function that can only be called from within another function?

eg can you do something like this?

private void a() {

b(); c(); ...do something else

private void b() { ..do something but can only be called from a() }

private void c() { ..do something but can only be called from a() }

}

The reason I want to do this is that function b() and c() split some implentation details of a() and they are just cleaner and easier to read in their own scope. However, these functions are of no use to the class as a() does some handling after they are called which must take place.

A: 

Not exactly but you could implement both within their own class. Mark b() as private.

Andrew Robinson
+10  A: 

Use an anonymous nested function maybe?

apphacker
Pendantic: You mean delegate of course.
Richard
Yes, a delegate.
apphacker
Pedantic: You mean pedantic of course.
Jason Slocomb
What good developer is not a pedant?
Cheeso
Pedants rule, OK. Or more precisely, exhibit certain of the conventional trappings of leadership
plinth
+1  A: 

The short answer is no; however, you can create an anonymous delegate or lambda expression as your internal b() method.

Ryan Riley
Yes, and See code above (by Josh).
Cheeso
Yes, Josh's code is also what I noted above; however, that's not the same as the sample in the original question, which appears to come from a JavaScript example. Josh's example, though, is perfect.
Ryan Riley
A: 

You could use the internal keyword and put both those functions inside the same class, while leaving other other functions in a different class: http://msdn.microsoft.com/en-us/library/7c5ka91b.aspx

Arthur Chaparyan
An internal method is more accessible than a private method...
Dave
+6  A: 

Using a delegate you can do:

public voidMyFunction()
{

   Func<string> myFunction=(s)=>Console.WriteLine(s);

   foreach(string str in myStringList)
   {
      myFunction(str);
   }
}
JoshBerke
Better than my solution. Nice example.
Andrew Robinson
This is the best way to do it.
Cheeso
delegates/lambdas are the way to go.
Jon Erickson
A: 

To gain the effect of only a() calling b(), either do as Andrew noted already, by putting a() and b() in a class and marking b() appropriately. If you're working inside of an assembly that you control totally, you could use internal instead of private if a() and b() will be in different classes, but in the same assembly. Then user code cannot call it (from outside of your assembly, that is, from their application program) and you can control via policy the writing of your assembly.

Michael Trausch
The problem with internal and private and other such modifiers - they work during a regular compile, but they can be circumscribed via reflection. I can, with reflection, read and even modify a private field on a class.
Cheeso
Then you can probably do it with an anon method, too; that gets compiled into its own method. Try looking at the disassembly (CLI) of a small example class w/ an anon method. It compiles to a private method (static or not depending on context). i.e.: http://zest.spicerack.trausch.us/~mbt/csharp-ex/
Michael Trausch
BTW, here's an example of using Reflection to tickle private fields: http://cheeso.members.winisp.net/srcview.aspx?file=PrivateReflection2.cs
Cheeso
A: 

You can also create something like this:

internal abstract class SecretFunctionWrapper
{
    private void MySecretFunction()
    {
        ...
    }

    protected void FunctionWhichCalls()
    {
        ...
        MySecretFunction();
    }
}

public MyRealClass : SecretFunctionWrapper
{
    ...
}

This will work only for one function. You can also try nested private class like this:

public class A
{
    private static class Wrapped
    {
        private static void A()
        {
            secred code
        }

        public static void B()
        {
            A();
        }
    }

    public void UsingA()
    {
        Wrapped.B();
    }
}
Migol
+2  A: 

Well you could use reflection and just get the calling method name and throw an exception if it were anything other than A.

http://www.csharp-examples.net/reflection-calling-method-name/

But if b and c are private they can only be called from within that class anyway, and if you're the only one that is writing the class, then i fail to see the problem. So it seems to me its not a coding problem but rather one of policy.

I'd just document the intent in the method headers/comments.

Similar Question Here - Note the comments on the answer

rism
b() and c() as nested delegates can access a()'s locals.
Simon Buchan
A: 

i dont know but maybe Code by Contracts may help but this is not supported natively

Oscar Cabrero
+2  A: 

You could use the StackFrame class to check at runtime who's the caller of the function:

public class MyClass
{
    public static void A()
    {
       B();
    }

    public static void B()
    {
        var stackTrace = new StackTrace();

        if (stackTrace.FrameCount < 1 || stackTrace.GetFrame(1).GetMethod() != typeof(MyClass).GetMethod("A"))
              throw new InvalidOperationException("Not called from A()");
    }
}

But that is

1) Only at runtime

2) Slow

3) A really dirty hack

Rauhotz
also won't work when using an obfuscator or when parts of the callstack are optimized away by the runtime
Wim Coenen
Also, stack walking has some rather unpalatable differences in 64 bit.
plinth
Stack walking in release mode can result in differences when functions are inlined.
JoshBerke
+8  A: 

I wouldn't worry about taking explicit steps to ensure b() and c() are only called by a().

It makes sense to worry about the public methods you expose on a class, since you're providing an interface to the outside world, potentially to people who don't have access to the source code of your class (or at the very least don't want to worry about the implementation details of your class).

Inside your class, though, you should feel free to have whatever private methods you want for whatever reasons you want. Code re-use is one reason to create a new private method, but creating multiple smaller, single-use methods to break up a larger one is also a perfectly valid (and common) reason.

Beyond that, for future maintainers of your code a simple comment like:

//this method should only be called by a()
private void b()
{
    ...
}

is going to be far more understandable than most of the other solutions presented here.

John Price
+1 because this makes code that is much more readable than the delegate/lambda answers. Although I'd use the /// auto doc comment on b() and c() so that the warnings would show up in the IntelliSense pop ups.
Zemm
I would really hope maintainers of my code find inner functions easy... wishful thinking?
Simon Buchan
@Simon it's not so much what's "easy" as what's "expected". In the straightforward case of just wanting to chop up a big method, why not stick with convention and use private methods?
John Price
Although an anonymous method / delegate answers the original question, I agree that your answer is the better practice. +1.
Randolpho
A: 

Maybe easier to use #region in this case

Avram