【问题标题】:C#: Function in Function possible?C#:函数中的函数可能吗?
【发布时间】:2011-08-18 13:33:55
【问题描述】:

是否可以在 C# 中的另一个方法中声明一个方法?

比如这样:

void OuterMethod()
{
    int anything = 1;
    InnerMethod();     // call function
    void InnerMethod()
    {
        int PlitschPlatsch = 2;
    }
}

【问题讨论】:

  • 为什么要这样做?你想解决什么问题?你想模拟什么情况?
  • @Cody Gray 我有一个包含大量代码的方法,我想对其进行结构化以便更好地阅读和理解。由于其他方法不需要这部分代码,所以我想到了将代码拆分到方法内部。
  • 是的,这正是我问的原因。很多乐于助人的人都在谈论 lambdas 和 Funcs,但这并不是您真正想要的。如果您认为需要从现有方法中重构代码,只需在.cs 文件中创建一个新方法,并确保将其标记为private。如果您不需要从其他任何地方调用它,那么不要。没有理由不必要地把事情复杂化。
  • Cody Gray:为什么每个结构都必须只有 3 个级别? (namespace, class, function) 这等于只有 3 级文件夹深度,这还不够。这是由用户决定的。某些功能可能更好地放置在同一类的其他功能不可访问的位置,因为它们可能只能一起调用或按特定顺序调用。 > 20 年的发展,没有人想到这一点。相反,我们有 lambda...

标签: c# .net methods


【解决方案1】:

更新:Local functions 在版本 7 C# 中添加。

void OuterMethod()
{
    int foo = 1;
    InnerMethod();
    void InnerMethod()
    {
        int bar = 2;
        foo += bar
    }
}

在以前的 C# 版本中,您必须使用如下操作:

void OuterMethod()
{
    int anything = 1;
    Action InnedMethod = () =>
    {
        int PlitschPlatsch = 2;
    };
    InnedMethod();
}

【讨论】:

  • 传参怎么样?
  • 错字:后面需要分号:foo += bar
【解决方案2】:

更新:C#7 添加了本地函数 (https://docs.microsoft.com/en-us/dotnet/articles/csharp/csharp-7#local-functions)

void OuterMethod()
{
    int foo = 1;

    InnerMethod();

    void InnerMethod()
    {
        int bar = 2;
        foo += bar
    }

}

在 C#7 之前的 C# 版本中,您可以声明 FuncAction 并获得类似的内容:

void OuterMethod()
{
    int foo = 1;
    Action InnerMethod = () => 
    {
        int bar = 2;
        foo += bar;
    } ;

    InnerMethod();
}

【讨论】:

  • @cheeso:因为它是一个简单的解决方案,语言支持得很好
  • 这在 C# 中不起作用。 “无法将匿名方法分配给隐式类型的局部变量”。
  • @nitro 它工作得很好。该示例不使用隐式类型的局部变量(即var 关键字)。它确实包含一些拼写错误,但我已修复。
【解决方案3】:

是的,有办法。在 C# 3.0 中,您拥有执行此操作的 Func<T> 类型。

例如,我昨天写了这个:

  var image = Image.FromFile(_file);
  int height = image.Height;
  int width = image.Width;
  double tan = height*1.00/width;
  double angle = (180.0 * Math.Atan(tan) / Math.PI);
  var bitmap = new System.Drawing.Bitmap(image, width, height);
  var g = System.Drawing.Graphics.FromImage(bitmap);
  int fontsize = 26; // starting guess
  Font font = null;
  System.Drawing.SizeF size;

  Func<SizeF,double> angledWidth = new Func<SizeF,double>( (x) =>
      {
          double z = x.Height * Math.Sin(angle) +
          x.Width * Math.Cos(angle);
          return z;
      });

  // enlarge for width
  do
  {
      fontsize+=2;
      if (font != null) font.Dispose();
      font = new Font("Arial", fontsize, System.Drawing.FontStyle.Bold);
      size = g.MeasureString(_text, font);
  }
  while (angledWidth(size)/0.85 < width);

目的是为现有图像添加水印。我想让水印文本的大小约为图像宽度的 85%。但我想把水印文字改成斜面,让它写成一个角度。这表明需要根据角度进行一些三角计算,我想要一个小函数来执行这项工作。 Func 非常适合。

上面的代码定义了一个Func(一个函数),它接受一个SizeF,并返回一个double,用于以给定角度绘制文本时的实际宽度。这个Func 是函数中的一个变量,而变量本身包含一个(对a 的引用)函数。然后我可以在我定义它的范围内调用那个“私有”函数。 Func 可以在其执行范围内访问在其之前定义的其他变量。因此,angle 变量可以在 angledWidth() 函数中访问。


如果您想要返回void 的可调用逻辑,您可以使用Action&lt;T&gt;,以同样的方式。 .NET 定义了接受 N 个参数的 Func 泛型,因此您可以使它们变得非常复杂。 Func 类似于返回非 void 的 VB 函数或 C# 方法; Action 类似于 VB Sub,或返回 void 的 C# 方法。

【讨论】:

    【解决方案4】:

    自提出这个问题以来已经过去了五年,现在 C# 7 即将到来。

    它计划包含本地功能,并且显然已经实现。

    本地函数(提案:#259)[当前在未来的分支中]

    https://github.com/dotnet/roslyn/issues/259

    【讨论】:

    • 我会注意到,在我个人看来,在你使用这个功能之前,你应该认真考虑你在做什么。您的方法可能变得太大而难以阅读。
    【解决方案5】:

    delegate 关键字就是这样做的。

    void OuterMethod()
    {
        var InnerMethod = delegate()
        {
            int PlitschPlatsch = 2;
        };
    
        int anything = 1;
        InnerMethod();
    }
    

    不要忘记,根据作用域,PlitschPlatsch 变量将无法在 InnerMethod 外部访问。

    【讨论】:

    • @Cheeso 可能是因为只有一种好方法可以做到这一点。此外,它完全不一样。
    • 这在 C# 中不起作用。 “无法将匿名方法分配给隐式类型的局部变量”。
    【解决方案6】:

    如果您主要想“隐藏”一个只是“帮助者”的方法......另一个选择是让你的帮助者private。这样它们就不会成为您班级公共接口的一部分。

    这样做的好处是可以在必要时重用助手;但它/它们不会是调用方法的“内部”。

    【讨论】:

      【解决方案7】:

      看看anonymous methods。我想这就是你要找的。​​p>

      【讨论】:

        猜你喜欢
        • 2012-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-09
        • 2010-12-16
        • 2014-11-27
        • 2021-08-02
        • 2021-07-14
        相关资源
        最近更新 更多