【问题标题】:Is it possible for a function to only be called from within another function?是否可以仅从另一个函数中调用函数?
【发布时间】:2010-10-10 05:21:00
【问题描述】:

在 C# 中是否可以创建一个只能从另一个函数中调用的函数?

例如,你能做这样的事情吗?

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()
}

}

我想这样做的原因是函数b()c() 拆分了a() 的一些实现细节,它们在自己的范围内更简洁、更易于阅读。但是,这些函数对类没有用,因为 a() 在调用它们之后会进行一些处理,而这些处理必须发生。

【问题讨论】:

    标签: c# function


    【解决方案1】:

    不完全是,但您可以在它们自己的类中实现两者。将 b() 标记为私有。

    【讨论】:

      【解决方案2】:

      也许使用匿名嵌套函数?

      【讨论】:

      • 学徒规则,OK。或者更准确地说,表现出某些传统的领导能力
      【解决方案3】:

      简短的回答是否定的;但是,您可以创建一个匿名委托或 lambda 表达式作为您的内部 b() 方法。

      【讨论】:

      • 是的,乔希的代码也是我上面提到的;但是,这与原始问题中的示例不同,后者似乎来自 JavaScript 示例。不过,乔希的例子是完美的。
      【解决方案4】:

      您可以使用 internal 关键字并将这两个函数放在同一个类中,而将其他其他函数放在不同的类中: http://msdn.microsoft.com/en-us/library/7c5ka91b.aspx

      【讨论】:

        【解决方案5】:

        使用委托你可以做到:

        public voidMyFunction()
        {
        
           Func<string> myFunction=(s)=>Console.WriteLine(s);
        
           foreach(string str in myStringList)
           {
              myFunction(str);
           }
        }
        

        【讨论】:

        • 比我的解决方案更好。很好的例子。
        • 这是最好的方法。
        • 代表/lambdas 是要走的路。
        【解决方案6】:

        要获得仅 a() 调用 b() 的效果,可以按照 Andrew 已经指出的方法,将 a() 和 b() 放在一个类中并适当地标记 b()。如果您在完全控制的程序集中工作,则可以使用 internal 而不是 private 如果 a() 和 b() 将在不同的类中,但在同一个程序集中。然后用户代码不能调用它(从您的程序集外部,即从他们的应用程序),您可以通过策略控制程序集的编写。

        【讨论】:

        • internal 和 private 以及其他此类修饰符的问题 - 它们在常规编译期间工作,但可以通过反射来限制它们。通过反射,我可以读取甚至修改类上的私有字段。
        • 那么你也可以用匿名方法来做;它被编译成自己的方法。尝试查看一个带有匿名方法的小型示例类的反汇编 (CLI)。它编译为私有方法(静态或不取决于上下文)。即:zest.spicerack.trausch.us/~mbt/csharp-ex
        • 顺便说一句,这是使用反射来处理私有字段的示例:cheeso.members.winisp.net/…
        【解决方案7】:

        你也可以这样创建:

        internal abstract class SecretFunctionWrapper
        {
            private void MySecretFunction()
            {
                ...
            }
        
            protected void FunctionWhichCalls()
            {
                ...
                MySecretFunction();
            }
        }
        
        public MyRealClass : SecretFunctionWrapper
        {
            ...
        }
        

        这仅适用于一种功能。您也可以尝试这样的嵌套私有类:

        public class A
        {
            private static class Wrapped
            {
                private static void A()
                {
                    secred code
                }
        
                public static void B()
                {
                    A();
                }
            }
        
            public void UsingA()
            {
                Wrapped.B();
            }
        }
        

        【讨论】:

          【解决方案8】:

          好吧,你可以使用反射,只获取调用方法的名称,如果它不是 A,则抛出异常。

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

          但是如果 b 和 c 是私有的,那么无论如何它们只能从该类中调用,并且如果您是唯一编写该类的人,那么我看不到问题所在。所以在我看来,这不是编码问题,而是政策问题。

          我只是在方法标头/cmets 中记录意图。

          Similar Question Here - Note the comments on the answer

          【讨论】:

          • b() 和 c() 作为嵌套代理可以访问 a() 的本地变量。
          • 虽然这是可能的,但直到运行时执行才会出现错误。如果可能的话,在设计时就应该优先考虑错误预防,所以我更喜欢委托解决方案。
          【解决方案9】:

          我不知道,但按合同编写代码可能会有所帮助,但本机不支持这一点

          【讨论】:

            【解决方案10】:

            您可以使用 StackFrame 类在运行时检查谁是函数的调用者:

            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()");
                }
            }
            

            但那是

            1) 仅在运行时

            2) 慢

            3) 一个非常肮脏的黑客攻击

            【讨论】:

            • 在使用混淆器或调用堆栈的某些部分被运行时优化掉时也不起作用
            • 此外,堆栈遍历在 64 位中也有一些令人不快的差异。
            • 释放模式下的堆栈遍历可能会导致内联函数时的差异。
            【解决方案11】:

            我不会担心采取明确的步骤来确保 b()c() 仅由 a() 调用。

            担心您在类上公开的 public 方法是有道理的,因为您正在为外部世界提供一个接口,可能是为那些无权访问源代码的人提供的你的班级(或者至少不想担心你班级的实现细节)。

            在你的类中,你应该可以随意使用任何你想要的私有方法,无论出于何种原因。代码重用是创建新私有方法的原因之一,但创建多个较小的、一次性使用的方法来分解较大的方法也是一个完全有效(且常见)的原因。

            除此之外,为您的代码的未来维护者提供一个简单的注释,例如:

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

            将比这里介绍的大多数其他解决方案更容易理解。

            【讨论】:

            • +1 因为这使得代码比委托/lambda 答案更具可读性。虽然我会在 b() 和 c() 上使用 /// 自动文档注释,以便警告会显示在 IntelliSense 弹出窗口中。
            • 我真的希望我的代码的维护者发现内部函数很容易......一厢情愿?
            • @Simon 与其说是“容易”,不如说是“预期”。在只是想切掉一个大方法的简单情况下,为什么不坚持约定并使用私有方法呢?
            • 虽然匿名方法/委托回答了原始问题,但我同意您的回答是更好的做法。 +1。
            • 这是提问者真正想要的。
            【解决方案12】:

            在这种情况下可能更容易使用#region

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-11-04
              • 1970-01-01
              • 2022-01-03
              • 2020-10-12
              • 1970-01-01
              • 2017-07-30
              • 1970-01-01
              • 2016-01-22
              相关资源
              最近更新 更多