Friday, April 8, 2011

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

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.

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

  • Use an anonymous nested function maybe?

    Richard : Pendantic: You mean delegate of course.
    apphacker : Yes, a delegate.
    Jason Slocomb : Pedantic: You mean pedantic of course.
    Cheeso : What good developer is not a pedant?
    plinth : Pedants rule, OK. Or more precisely, exhibit certain of the conventional trappings of leadership
  • The short answer is no; however, you can create an anonymous delegate or lambda expression as your internal b() method.

    Cheeso : Yes, and See code above (by Josh).
    Ryan Riley : 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.
  • 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

    Dave : An internal method is more accessible than a private method...
  • Using a delegate you can do:

    public voidMyFunction()
    {
    
       Func<string> myFunction=(s)=>Console.WriteLine(s);
    
       foreach(string str in myStringList)
       {
          myFunction(str);
       }
    }
    
    Andrew Robinson : Better than my solution. Nice example.
    Cheeso : This is the best way to do it.
    Jon Erickson : delegates/lambdas are the way to go.
  • 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.

    Cheeso : 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.
    Michael Trausch : 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/
    Cheeso : BTW, here's an example of using Reflection to tickle private fields: http://cheeso.members.winisp.net/srcview.aspx?file=PrivateReflection2.cs
  • 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();
        }
    }
    
  • 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

    Simon Buchan : b() and c() as nested delegates can access a()'s locals.
  • i dont know but maybe Code by Contracts may help but this is not supported natively

  • 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

    Wim Coenen : also won't work when using an obfuscator or when parts of the callstack are optimized away by the runtime
    plinth : Also, stack walking has some rather unpalatable differences in 64 bit.
    JoshBerke : Stack walking in release mode can result in differences when functions are inlined.
  • 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.

    Zemm : +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.
    Simon Buchan : I would really hope maintainers of my code find inner functions easy... wishful thinking?
    John Price : @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?
    Randolpho : Although an anonymous method / delegate answers the original question, I agree that your answer is the better practice. +1.
  • Maybe easier to use #region in this case

0 comments:

Post a Comment