web-dev-qa-db-ja.com

C#:関数内の関数は可能ですか?

C#の別のメソッド内でメソッドを宣言することは可能ですか?

そのような例:

void OuterMethod()
{
    int anything = 1;
    InnedMethod();
    void InnerMethod()
    {
        int PlitschPlatsch = 2;
    }
}
62
Non

更新: ローカル関数 バージョン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();
}
56
JaredPar

更新: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#のバージョンでは、FuncまたはActionを宣言して、同様のものを取得できます。

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

    InnerMethod();
}
41
jeroenh

はい、方法があります。 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<T>_ を同じ方法で使用できます。 .NETはN個の引数を受け入れるFuncジェネリックを定義しているため、かなり複雑にすることができます。 FuncはVB関数または非voidを返すC#メソッドのようなものです。アクションはVB Subまたはvoidを返すC#メソッドのようなものです。

16
Cheeso

この質問が出されてから5年が経ち、C#7が登場します。

ローカル関数を含める予定で、明らかにすでに実装されています。

ローカル関数(提案:#259)[現在は将来のブランチ]

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

9
dss539

delegateキーワードはまさにそれを行います。

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

    int anything = 1;
    InnerMethod();
}

スコープごとに、PlitschPlatsch変数にInnerMethodの外部からアクセスできないことを忘れないでください。

3
zneak

主に「ヘルパー」であるメソッドを「非表示」にしたい場合、別のオプションはヘルパーをprivateにすることです。そうすれば、クラスのパブリックインターフェイスの一部にはなりません。

これには、必要に応じてヘルパーを再利用できるという利点があります。しかし、それは、呼び出しメソッドの「内部」にはなりません。

1
David

匿名メソッド をご覧ください。それがあなたが探しているものだと思います。

1
T.K.