C#: Функция в функции возможно?


можно ли объявить метод в другом методе в C#?

например вот так:

void OuterMethod()
{
    int anything = 1;
    InnedMethod();
    void InnerMethod()
    {
        int PlitschPlatsch = 2;
    }
}
7 52

7 ответов:

обновление: локальные функции где добавлено в версии 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();
}

обновление: 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# до C#7, Вы можете объявить a Func или Action и получить что-то подобное:

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

    InnerMethod();
}

да, есть способы. С 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 и возвращает a double, для фактической ширины текста, когда он нарисован под заданным углом. Это Func - это переменная внутри функции, а сама переменная содержит (ссылку на A) функцию. Затем я могу вызвать эту "частную" функцию в области, где я ее определил. Func имеет доступ к другим переменным, которые определяются перед ним, в области его выполнения. Итак,angle переменная доступна внутри .


если вы хотите вызвать логику, которая возвращает void, вы можете использовать Action<T> таким же образом. .NET определяет универсалии Func, которые принимают N аргументов, поэтому вы можете сделать их довольно сложными. В функции как функции VB или C# метод, который возвращает не void; действие как суб VB или на C# метод, который возвращает void.

прошло пять лет с тех пор, как этот вопрос был задан, и теперь C# 7 идет.

он запланирован для включения локальных функций и, по-видимому, уже реализован.

локальные функции (предложение: #259) [в настоящее время в будущей ветке]

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

The delegate ключевое слово делает.

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

    int anything = 1;
    InnerMethod();
}

не забывайте, что согласно определения PlitschPlatsch переменная не будет доступна за пределами InnerMethod.

посмотри анонимные методы. Я думаю, что это то, что вы ищете.

Если вы ищете в основном, чтобы" скрыть "метод, который является просто" помощником"... другой вариант-сделать ваш помощник(ы) private. Таким образом, они не становятся частью публичного интерфейса класса.

это имеет то преимущество, что помощник(ы) может быть повторно использован при необходимости; но он / они не будут "внутренними" для вызывающего метода.