2010年4月12日月曜日

C# 4.0 のオプショナルパラメータと名前付き引数について

このエントリーをはてなブックマークに追加
on Mono 2.6.1

オプショナルパラメータと名前付き引数?


なるほど。

Mono では、Mono 2.6 から C# 4.0 に部分的に対応していて、


C# 4.0 対応ビルドコマンドとして、dmcs を提供している。サツガイされそう。

$ dmcs foo.cs

それで、オプショナルパラメータと名前付き引数は対応済ということなので、次のコードを試してみると、
using System;

namespace Example
{
  public class Program
  {
    static void DoSomething(int x = 0, int y = 1)
    {
      Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
    }

    public static void Main(string[] args)
    {
      DoSomething();
      DoSomething(1);
      DoSomething(2, 3);
      DoSomething(x: 4);
      DoSomething(y: 5);
      //DoSomething(x: 6, 7); // Compilation failed : error CS1738: Named arguments must appear after the positional arguments
      DoSomething(8, y: 9);
      DoSomething(x: 10, y: 11);
      DoSomething(y: 13, x: 12);
    }
  }
}
/*
 * Build:
 *
 *   dmcs csharp4test1.cs
 *
 * Run:
 *
 *   mono csharp4test1.exe
 *
 */

コメントにした箇所は、ビルドエラーになるけど、こういう仕様か(名前付き引数の後に通常のスタイルで引数をセットできない)?

以下、実行例。

$ dmcs csharp4test1.cs
$ mono csharp4test1.exe 
0 + 1 = 1
1 + 1 = 2
2 + 3 = 5
4 + 1 = 5
0 + 5 = 5
8 + 9 = 17
10 + 11 = 21
12 + 13 = 25

さらに、次のコードを追加してみると、
static void DoSomething()
{
  DoSomething(1, 2);
}
$ dmcs csharp4test1.cs
csharp4test1.cs(19,7): error CS0121: The call is ambiguous between the following methods or properties: `Example.Program.DoSomething()' and `Example.Program.DoSomething(int, int)'
csharp4test1.cs(7,17): (Location of the symbol related to previous error)
csharp4test1.cs(12,17): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings

そりゃそうだ、こんな類のオーバーロードはサツガイされる。

また、次の変更をしてみると、
static void add(int x, int y)
{
  Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
}

static void DoSomething(Action<int, int> action = add, int x = 0, int y = 1)
{
  action(x, y);
}
$ dmcs csharp4test1.cs
csharp4test1.cs(12,55): error CS1736: The expression being assigned to optional parameter `action' must be a constant or default value
Compilation failed: 1 error(s), 0 warnings

なるほど、駄目か。

ということで、
using System;

namespace Example
{
  public class Program
  {
    static void add(int x, int y)
    {
      Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
    }

    static void DoSomething(Action<int, int> action, int x = 0, int y = 1)
    {
      if (action == null) action = add;
      action(x, y);
    }

    public static void Main(string[] args)
    {
      Action<int, int> sub = (x, y) => Console.WriteLine("{0} - {1} = {2}", x, y, x - y);
      Action<int, int> mul = (x, y) => Console.WriteLine("{0} * {1} = {2}", x, y, x * y);
      Action<int, int> div = (x, y) => Console.WriteLine("{0} / {1} = {2}", x, y, x / y);

      DoSomething(null);
      DoSomething(sub);
      DoSomething(sub, 1);
      DoSomething(sub, 2, 3);
      DoSomething(sub, x: 4);
      DoSomething(sub, y: 5);
      DoSomething(sub, 6, y: 7);
      DoSomething(sub, x: 8, y: 9);
      DoSomething(sub, y: 11, x: 10);
      DoSomething(action: mul);
      DoSomething(action: mul, x: 12);
      DoSomething(action: mul, y: 13);
      DoSomething(action: div, x: 14, y: 15);
      DoSomething(x: 16, y: 17, action: div);
    }
  }
}
/*
 * Build:
 *
 *   dmcs csharp4test2.cs
 *
 * Run:
 *
 *   mono csharp4test2.exe
 *
 */

実行例。

$ dmcs csharp4test2.cs
$ mono csharp4test2.exe 
0 + 1 = 1
0 - 1 = -1
1 - 1 = 0
2 - 3 = -1
4 - 1 = 3
0 - 5 = -5
6 - 7 = -1
8 - 9 = -1
10 - 11 = -1
0 * 1 = 0
12 * 1 = 12
0 * 13 = 0
14 / 15 = 0
16 / 17 = 0

オプション的にデフォルトのメソッドを設定できるようにしたいけど、何か、うまい手はないかな。

0 件のコメント:

コメントを投稿