C# 13の新機能を理解する――paramsコレクションと新しいロックセマンティクス
【C#で知っておくべき新機能】最新バージョンを徹底解説! 第6回
ダウンロード サンプルファイル (6.5 KB)
paramsコレクション(Params collections)
C# 13では、params(可変長引数)に、コレクション式で使える型を利用できるようになりました。
C#のメソッドには、可変長引数を受け取る仕組みがあります。これは、paramsと呼ばれます。配列を受け取るメソッドにおいてparamsを使うと、個別の変数をそのままメソッドの引数として渡すことができます。
double a = 3.14159, b = 1.41421, c = 2.2362, d = 2.71828, e = 1.61803;
ave = CalcAverageParams(a, b, c, d, e); // 直接渡せる
Console.WriteLine($"With params: {ave}"); // With params: 2.225662
double CalcAverageParams(params double[] a) // paramsを指定して配列で受ける
{
double sum = 0;
for (int i = 0; i < a.Length; i++)
{
sum += a[i];
}
return sum / a.Length;
}
従来は、paramsで渡せるのは基本的に配列のみでしたが、C# 13では配列を含むコレクション式を渡せるようになりました。コレクション式とは、C# 12で導入された、配列やコレクションを大カッコ([ ])で初期化できる記法です。このコレクション式については第4回で紹介しました。
C# 13では、上記のリストは以下のように書き換えられます。
double ave;
double a = 3.14159, b = 1.41421, c = 2.2362, d = 2.71828, e = 1.61803;
ave = CalcAverageList(a, b, c, d, e);
Console.WriteLine($"With List: {ave}"); // With List: 2.225662
double CalcAverageList(params List<double> a)
…関数の中身はCountプロパティに書き換えただけなので省略…
ave = CalcAverageIEnumerable(a, b, c, d, e);
Console.WriteLine($"With IEnumerable: {ave}"); // With IEnumerable: 2.225662
double CalcAverageIEnumerable(params IEnumerable<double> a)
…関数の中身はforeach文に書き換えただけなので省略…
ave = CalcAverageReadOnlySpan(a, b, c, d, e);
Console.WriteLine($"With ReadOnlySpan: {ave}"); // With ReadOnlySpan: 2.225662
double CalcAverageReadOnlySpan(params ReadOnlySpan<double> a)
…関数の中身は配列版に同じなので省略…
ave = CalcAverageSpan(a, b, c, d, e);
Console.WriteLine($"With Span: {ave}"); // With Span: 2.225662
double CalcAverageSpan(params Span<double> a)
…関数の中身は配列版に同じなので省略…
新しいロックセマンティクス(New lock object)
C# 13では、lock文でLockオブジェクトを特別扱いするようになりました。
lock文は、マルチスレッド環境において排他制御を行うための構文です。以下のように、排他制御に使うオブジェクト(同期オブジェクト)を、排他制御の必要な期間(クリティカルセクション)の開始時に自動でロックして(排他ロック)、終了時に自動で解放(アンロック)する処理を記述できます。
同期オブジェクトがロックされている間、他のスレッドは同期オブジェクトをロックしたくてもできないので、クリティカルセクション内で排他的な処理を記述できます。
同期オブジェクト生成
lock(同期オブジェクト) // 排他ロック(二重ロック不可)
{
クリティカルセクション // ここを実行できるのは常に単一のスレッドのみ
} // アンロック
従来のC#では、同期オブジェクトには任意のオブジェクト(objectオブジェクトなど)などを使うことで、lock文において排他制御のためのSystem.Threading.Monitorクラスを使うコードに展開されていました。Monitorクラスによる排他制御は速度面で不利な面があるため、.NET 9で新しい排他制御のためのクラスLockが追加されました。これに伴い、同期オブジェクトにはLockオブジェクトを使います。lock文の書き方自体は変わりませんが、C# 13ではSystem.Threading.Lockクラスを使うコードに展開されます。
以下は、2つのロック方法にかかる時間を比較する例です。複数のスレッドを起動し、ダミーの計算処理を実行しています。スレッドの起動と終了の時間をStopwatchクラスで計測して合計値とともに表示します。
using System.Diagnostics;
const int NumberOfThread = 10; // スレッドの個数
const int NumberOfLoop = 100000; // スレッド内で実行するループの回数
long sum; // ダミーの計算処理用
var sw = new Stopwatch(); // 実行時間計測用
// 従来のlock
var syncObject = new object(); // 任意のオブジェクト
sum = 0; // 計算値をリセット
sw.Reset(); // 計測開始
sw.Start();
Parallel.For(0, NumberOfThread, i => // スレッド起動
{
for (int j = 0; j < NumberOfLoop; j++) // 繰り返し開始
{
lock (syncObject) // 同期オブジェクトのロック
{
int tmp = sum + i; // ダミーの計算処理
sum = tmp + j;
}
}
});
sw.Stop(); // 計測終了
Console.Write("sync object: {0}: {1}\n", sum, sw.Elapsed); // 結果表示
// 新しいlock
var lockObject = new Lock(); // Lockオブジェクトとする
sum = 0; // 計算値をリセット
sw.Reset();
sw.Start();
Parallel.For(0, NumberOfThread, i =>
{
for (int j = 0; j < NumberOfLoop; j++)
{
lock (lockObject) // 同期オブジェクト(Lockオブジェクト)のロック
{
int tmp = sum + i; // ダミーの計算処理
sum = tmp + j;
}
}
});
sw.Stop();
Console.Write("lock object: {0}: {1}\n", sum, sw.Elapsed);
実行すると、Lockオブジェクトを用いた繰り返しの方が高速であることが分かります。
sync object: 500400000: 00:00:00.0213048 lock object: 500400000: 00:00:00.0045708
この記事は参考になりましたか?
- 【C#で知っておくべき新機能】最新バージョンを徹底解説!連載記事一覧
- この記事の著者
-
WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
