メソッドを呼び出すときに名前付き引数を使うには?[C#/VB].NET TIPS

名前付き引数を使用すると、メソッド呼び出し時に順不同で特定の引数だけを指定できる。多数のオプション引数を持つメソッドを呼び出す場合には、とりわけ役に立つ。

» 2017年06月14日 05時00分 公開
[山本康彦BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

 名前付き引数とは、メソッドを呼び出すときにどの引数にどの値を渡すのかを名前で指定できる機能である。本稿では、名前付き引数の使い方と、そのメリットを解説する。

メソッドを呼び出すときに名前付き引数を使うには?

 名前付き引数はメソッドを呼び出す側の機能であり、呼び出されるメソッド側に特別な用意は何も必要ない。呼び出すときの引数の前に、引数名+「:」(C#)/「:=」(VB)を付けるだけである(次のコード)。

 名前付き引数を使うことで、引数の並び順を自由にできる。また、オプション引数(省略可能な引数)と組み合わせると、必要な引数だけを好きな順序で渡せる。

using static System.Console;
……省略……

// オプション引数に対応したメソッド
public static int SampleMethod1(int x=0, int y=0, int z=0)
  => x + y * 2 + z * 3;

……省略……

// 通常のメソッド呼び出し
WriteLine($"SampleMethod1(1,2,3)={SampleMethod1(1,2,3)}");
// 出力:SampleMethod1(1,2,3)=14

// 名前付き引数を使う
WriteLine($"SampleMethod1(x:1,y:2,z:3)={SampleMethod1(x:1,y:2,z:3)}");
// 出力:SampleMethod1(x:1,y:2,z:3)=14

// 引数の順序を変えられる
WriteLine($"SampleMethod1(z:3,x:1,y:2)={SampleMethod1(z:3,x:1,y:2)}");
// 出力:SampleMethod1(z:3,x:1,y:2)=14

// 呼び出すメソッドがオプション引数に対応しているなら、
// 必要な引数だけを任意の順序で与えられる
WriteLine($"SampleMethod1(z:3,x:1)={SampleMethod1(z:3,x:1)}");
// 出力:SampleMethod1(z:3,x:1)=10

// 後ろだけに名前引数を使う
WriteLine($"SampleMethod1(1,z:2,y:3)={SampleMethod1(1, z:2, y:3)}");
// 出力:SampleMethod1(1,z:2,y:3)=13

// 後ろに名前なしの通常の引数は使えない(コンパイル不可)
// WriteLine($"SampleMethod1(x:1,y:2,3)={SampleMethod1(x:1, y:2, 3)}");

Imports System.Console
……省略……

' オプション引数に対応したメソッド
Public Function SampleMethod1(Optional x As Integer = 0,
                              Optional y As Integer = 0,
                              Optional z As Integer = 0) As Integer
  Return x + y * 2 + z * 3
End Function

……省略……

' 通常のメソッド呼び出し
WriteLine($"SampleMethod1(1,2,3)={SampleMethod1(1, 2, 3)}")
' 出力:SampleMethod1(1,2,3)=14

' 名前付き引数を使う
WriteLine($"SampleMethod1(x:=1,y:=2,z:=3)={SampleMethod1(x:=1, y:=2, z:=3)}")
' 出力:SampleMethod1(x:=1,y:=2,z:=3)=14

' 引数の順序を変えられる
WriteLine($"SampleMethod1(z:=3,x:=1,y:=2)={SampleMethod1(z:=3, x:=1, y:=2)}")
' 出力:SampleMethod1(z:=3,x:=1,y:=2)=14

' 呼び出すメソッドがオプション引数に対応しているなら、
' 必要な引数だけを任意の順序で与えられる
WriteLine($"SampleMethod1(z:=3,x:=1)={SampleMethod1(z:=3, x:=1)}")
' 出力:SampleMethod1(z:=3,x:=1)=10

' 後ろだけに名前引数を使う
WriteLine($"SampleMethod1(1,z:=2,y:=3)={SampleMethod1(1, z:=2, y:=3)}")
' 出力:SampleMethod1(1,z:=2,y:=3)=13

' 後ろに名前なしの通常の引数は使えない(コンパイル不可)
' WriteLine($"SampleMethod1(x:=1,y:=2,3)={SampleMethod1(x:=1, y:=2, 3)}")

メソッドを呼び出すときに名前付き引数を使う例(上:C#、下:VB)

メソッド側の引数名を変えるとエラー!

 名前付き引数は、名前を間違えるとコンパイルエラーになる(次のコード)。

 当然のことなのだが、特にクラスライブラリでは引数名の変更は慎重にしよう。クラスライブラリの側でメソッドの引数名だけ変更して呼び出し側は元のままの場合、引数名を間違えたのと同じことになるからだ。同じソリューション内ならVisual Studioのリファクタリング機能を使って引数名を変更すれば呼び出し側も自動的に修正してくれるが、バイナリを利用するクラスライブラリではそうはいかないのである。

// 引数名が違うとコンパイルできない
// WriteLine($"SampleMethod1(A:1,B:2,C:3)={SampleMethod1(A:1,B:2,C:3)}");
// すなわち、ライブラリ側で引数名を変えると、利用側でエラーが発生する

' 引数名が違うとコンパイルできない
' WriteLine($"SampleMethod1(A:=1,B:=2,C:=3)={SampleMethod1(A:=1, B:=2, C:=3)}")
' すなわち、ライブラリ側で引数名を変えると、利用側でエラーが発生する

引数名を間違えて名前付き引数を使うとコンパイルできない(上:C#、下:VB)
先ほどのSampleMethod1メソッドを呼び出すコードなのだが、引数名を間違えているためコンパイルエラーになる。
当然のことなのだが、メソッド側の引数名だけを変更して、呼び出し側を変更し忘れると同じことになる。

Excelを利用する例

 名前付き引数は、たくさんのオプション引数を持っているメソッドを呼び出すときに威力を発揮する。

 多数の引数を持つメソッドを使う例として、ExcelのCOMインタフェースを取り上げてみよう。Excelを起動してファイルを読み込ませるコードの概略は、次のコードのようになる。名前付き引数とオプション引数が使えなかったC# 3.0までは、コメントアウトした部分に示したように全ての引数を書かなければならなかったのだ。

// 参照に、COMのタイプライブラリにある
//「Microsoft Excel xx.x Object Libray」(xx.xはバージョン番号)を追加する
// 冒頭に「using System.Runtime.InteropServices;」を追加する
// 冒頭に「using static System.Console;」を追加する
string sampleFile
  = System.IO.Path.Combine(Environment.CurrentDirectory, "Sample.xlsx");

// Excelを起動する
var excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.Visible = true;

// 既存のファイル"Sample.xlsx"をワークブックに読み込む
var workbooks = excelApp.Workbooks;
// C# 4.0以前(名前付き引数とオプション引数が使えない)ではこう書くしかなかった
// var workbook = workbooks.Open(sampleFile, Type.Missing, true,
//   Type.Missing, "@password", Type.Missing, Type.Missing,
//   Type.Missing, Type.Missing, Type.Missing, Type.Missing,
//   Type.Missing, Type.Missing, Type.Missing, Type.Missing);

// 名前付き引数とオプション引数を使えば、シンプルに書ける
var workbook = workbooks.Open(sampleFile, ReadOnly: true, Password: "@password");

WriteLine("Excelファイルを読み取り専用で開きました");
WriteLine("何かキーを押すとExcelを閉じます");
ReadKey();

// 以下の解放処理は、本来は個別にtry〜finallyしなければならない
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
excelApp.Quit(); Marshal.ReleaseComObject(excelApp);

' 参照に、COMのタイプライブラリにある
'「Microsoft Excel xx.x Object Libray」(xx.xはバージョン番号)を追加する
' 冒頭に「Imports System.Runtime.InteropServices」を追加する
' 冒頭に「Imports System.Console」を追加する
Dim sampleFile As String _
  = System.IO.Path.Combine(Environment.CurrentDirectory, "Sample.xlsx")

' Excelを起動する
Dim excelApp = New Microsoft.Office.Interop.Excel.Application()
excelApp.Visible = True

' 既存のファイル"Sample.xlsx"をワークブックに読み込む
Dim workbooks = excelApp.Workbooks
' VB.NETでは最初からこのようにオプション引数と名前付き引数が使えた
Dim workbook = workbooks.Open(sampleFile, ReadOnly:=True, Password:="@password")

WriteLine("Excelファイルを読み取り専用で開きました")
WriteLine("何かキーを押すとExcelを閉じます")
ReadKey()

' 以下の解放処理は、本来は個別にTry〜Finallyしなければならない
Marshal.ReleaseComObject(workbook)
Marshal.ReleaseComObject(workbooks)
excelApp.Quit() : Marshal.ReleaseComObject(excelApp)

Excelを起動してファイルを読み込ませる例(上:C#、下:VB)
実行ファイルと同じディレクトリにあるExcelワークブック(「@password」というパスワードで保護)を読み取り専用で開くサンプルコード。サンプルコードということで、COMオブジェクトの解放処理は簡易的に記述している。実際には、COMオブジェクトを1つ取得するごとにtryブロックで囲み、対応するfinallyブロックでそのCOMオブジェクトだけを(存在することを確かめたうえで)解放するように記述することになる。また、Microsoft.Office.Interop.Excelアセンブリへの参照の追加と、「using System.Runtime.InteropServices;」(C#)または「Imports System.Runtime.InteropServices」(VB)の記述が必要だ。

まとめ

 名前付き引数は、メソッドを呼び出す側で使える機能だ。呼び出すメソッドがたくさんのオプション引数を持っているときに便利である。

利用可能バージョン:Visual Basic .NET以降/Visual Studio 2010(C# 4.0)以降
カテゴリ:C# 処理対象:言語構文
カテゴリ:Visual Basic .NET 処理対象:言語構文
関連TIPS:オプション引数が使えるメソッドを作るには?[C#/VB]
関連TIPS:Excelファイルにアクセスするには?[C#、VB]
関連TIPS:数値を右詰めや0埋めで文字列化するには?[C#、VB]


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。