From bd51e4cf5de9723ab9f73844c6c90cb1450358f5 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 9 Jan 2026 20:15:56 +0900 Subject: [PATCH 01/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80=E3=81=AE=E3=83=89?= =?UTF-8?q?=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 7 +++++++ sidebars.js | 1 + 2 files changed, 8 insertions(+) create mode 100644 docs/reference/values-types-variables/using.md diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md new file mode 100644 index 00000000..c1cb7f84 --- /dev/null +++ b/docs/reference/values-types-variables/using.md @@ -0,0 +1,7 @@ +--- +sidebar_label: using宣言 +--- + +# 新しい変数宣言 using + +using宣言(using declaration)とは、JavaScriptに導入された新しい変数宣言であり、スコープを抜けるときに自動的にクリーンアップ処理を実行するための構文です。TypeScriptでは5.7で導入されました。 diff --git a/sidebars.js b/sidebars.js index 28fbbfa4..1479a938 100644 --- a/sidebars.js +++ b/sidebars.js @@ -169,6 +169,7 @@ module.exports = { "reference/values-types-variables/type-assertion-as", "reference/values-types-variables/const-assertion", "reference/values-types-variables/satisfies", + "reference/values-types-variables/using", "reference/values-types-variables/definite-assignment-assertion", "reference/values-types-variables/typeof-operator", "reference/values-types-variables/equality", From 7726f441c8c79e6defd14ac3a3e44148f9e7d8ac Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 9 Jan 2026 20:31:13 +0900 Subject: [PATCH 02/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=9B=B8?= =?UTF-8?q?=E3=81=8D=E5=87=BA=E3=81=97=E6=96=87=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index c1cb7f84..cb5d3a53 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,4 +4,5 @@ sidebar_label: using宣言 # 新しい変数宣言 using -using宣言(using declaration)とは、JavaScriptに導入された新しい変数宣言であり、スコープを抜けるときに自動的にクリーンアップ処理を実行するための構文です。TypeScriptでは5.7で導入されました。 +using宣言(using declaration)とは、JavaScriptに導入される(ECMAScriptのプロポーザルではStage2)新しい変数宣言であり、宣言した変数のスコープを抜けるときに自動的にクリーンアップ処理を実行されることで明示的にリソース管理を行なうことができる構文です。TypeScriptでは5.2からサポートされています。 + From c1123779f0349bacaf8a11ed2e7f057f4bbe139a Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 9 Jan 2026 20:37:58 +0900 Subject: [PATCH 03/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=9B=B8?= =?UTF-8?q?=E3=81=8D=E5=87=BA=E3=81=97=E6=96=87=E3=82=92=E7=B0=A1=E6=BD=94?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index cb5d3a53..7b603b96 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,5 +4,6 @@ sidebar_label: using宣言 # 新しい変数宣言 using -using宣言(using declaration)とは、JavaScriptに導入される(ECMAScriptのプロポーザルではStage2)新しい変数宣言であり、宣言した変数のスコープを抜けるときに自動的にクリーンアップ処理を実行されることで明示的にリソース管理を行なうことができる構文です。TypeScriptでは5.2からサポートされています。 +using宣言(using declaration)とは、JavaScriptに導入される(ECMAScriptのプロポーザルではStage2)新しい変数宣言であり、明示的にリソース管理を行なうことができる構文です。TypeScriptでは5.2からサポートされています。 + From 3650f808c5e2b194ca950f5ec8c5aa4f5676acc1 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 9 Jan 2026 20:51:53 +0900 Subject: [PATCH 04/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=9B=B8?= =?UTF-8?q?=E3=81=8D=E5=87=BA=E3=81=97=E6=96=87=E3=82=92=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 7b603b96..a9787ac8 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,6 +4,7 @@ sidebar_label: using宣言 # 新しい変数宣言 using -using宣言(using declaration)とは、JavaScriptに導入される(ECMAScriptのプロポーザルではStage2)新しい変数宣言であり、明示的にリソース管理を行なうことができる構文です。TypeScriptでは5.2からサポートされています。 +using宣言(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage2の機能です。TypeScriptでは5.2からサポートされています。 +using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで明示的なリソース管理(Explicit Resource Management)を実現できます。 From dd364a0154201f097b4cdd9fe46ac222820c6e97 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 23 Jan 2026 20:51:30 +0900 Subject: [PATCH 05/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E3=83=AA?= =?UTF-8?q?=E3=82=BD=E3=83=BC=E3=82=B9=E7=AE=A1=E7=90=86=E3=81=A8=E3=83=AA?= =?UTF-8?q?=E3=83=BC=E3=82=AF=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E8=AA=AC?= =?UTF-8?q?=E6=98=8E=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index a9787ac8..4cb516c7 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -8,3 +8,67 @@ using宣言(using declaration)とは、JavaScriptに導入される新しい変 using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで明示的なリソース管理(Explicit Resource Management)を実現できます。 +## リソースとは + +using宣言を理解するための前提として「リソース」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 + +- ファイル(具体的にはファイルハンドル) +- ネットワーク接続(ネットワークソケット) +- DB接続(データベースコネクション) +- メモリ領域 + +JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 + +メモリ領域以外のリソースの管理はGCは行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 + +```ts +async function readFile(fileName: string): Promise { + // ファイルを開く + const file = await Deno.open(fileName); + try { + // ファイルを読み取る + const buffer = new Uint8Array(5); + const bytesRead = await file.read(buffer); + console.log(bytesRead); + } finally { + // 必ずファイルを閉じる(リソースを解放) + file.close(); + } +} +``` + +メモリやファイルといったリソースは利用後に必ず解放する必要があります。この解放処理を忘れると、リソースリークという問題が発生します。 + +## リソースリークとは + +「リソースリーク」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。例えば、メモリ解放を忘れた場合には「メモリリーク」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 + +以下のようにリソースの種類により、リークの問題は故障が変わりますが、一般にはリソースリークと呼ばれます。 + +- ファイルハンドルリーク +- ソケットリーク +- DB接続リーク + +メモリリーク以外のリソースリークでも、システムパフォーマンスの低下やクラッシュといった問題が発生する可能性があります。 + +リソースの使用後には必ず解放を行いところですが、解放し忘れてしまう場合もあるでしょう。GCがメモリ解放を自動的に行ってくれるように、非メモリリソースの解放も自動的に行ってくれたら楽になるでしょう。 + +## usingの登場 + +そこで、 using宣言が現れました。using宣言で宣言された変数に紐づけられたリソースは、その変数がスコープを抜けるときに `Symbol.dispose` で指定されたコールバック関数が呼び出さます。このコールバック処理に記述されたリソースの解放処理が自動的に実行されます。 + +```ts +{ + // 変数初期化によるリソースの確保 + using file = Deno.openSync(); + + file.writeSync(); + + file.readSync(); +} // スコープを抜けると自動的にfileに紐づくリソースの解放処理が呼ばれる +``` + +スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。 + +実は、このようなパターンはRAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 + From a7943f77495732f08088b540a4dbdd0da04fd0b0 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:06:32 +0900 Subject: [PATCH 06/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20RAII=E3=83=91?= =?UTF-8?q?=E3=82=BF=E3=83=BC=E3=83=B3=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B?= =?UTF-8?q?=E4=BB=96=E3=81=AE=E8=A8=80=E8=AA=9E=E3=81=AE=E4=BE=8B=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 4cb516c7..7f9cb533 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -72,3 +72,31 @@ async function readFile(fileName: string): Promise { 実は、このようなパターンはRAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 +## 他の言語でのパターン + +### RAIIパターン + +RAII(Resource Acquisition Is Initialization)パターンとは、文字通り「リソース取得は初期化」を意味しており、リソースの確保と解放を変数の初期化と破棄に結びつけるというプログラミングパターンを表します。 + +JavaScriptの `using` を含め、以下に挙げるようなプログラミング言語では類似のRAIIパターンを採用しています。 + +### C#のusing句 + +JavaScriptの `using` に似ているのがC#の `using` です。以下のように `using` 句に指定されたオブジェクト(`SqlConnection`)は `IDisposable` インターフェースを実装している必要があります。 + +```cs +using(var connection = new SqlConnection(connectionString)) +{ + // ... +} +``` + +`IDisposable` インターフェースを実装していることで、スコープ脱出時に、`IDisposable`インターフェースの `Dispose` メソッドによるリソース解放が行われます。 + +### Rustのdropメソッド + +RustもRAIIパターンを採用しており、所有権という概念のもとで、メモリを含むあらゆるリソースの解放タイミングを スコープの脱出時に定めており、コードの構造によって解放のタイミングが決定されます。これによって、リソースリークを静的に防ぎ安全性を担保します。 + +このような所有権に基づいたリソース管理はまさに、RAIIに基づいたリソース管理の方法となっています。 + +Rustの `Drop` トレイトに存在する `drop` というメソッドがこれを実現しています。オブジェクトがスコープを抜けるときにはこのメソッドが自動的に呼び出されて、登録されているリソース解放の処理を行います。 From 911059170efab8b22e1f08173194ee573b17bbdf Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:19:27 +0900 Subject: [PATCH 07/31] =?UTF-8?q?=E8=AA=A4=E5=AD=97=E8=84=B1=E5=AD=97?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 7f9cb533..eb8f0815 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -43,7 +43,7 @@ async function readFile(fileName: string): Promise { 「リソースリーク」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。例えば、メモリ解放を忘れた場合には「メモリリーク」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 -以下のようにリソースの種類により、リークの問題は故障が変わりますが、一般にはリソースリークと呼ばれます。 +以下のようにリソースの種類により、リークの問題は呼称が異なりますが、一般にはリソースリークと呼ばれます。 - ファイルハンドルリーク - ソケットリーク @@ -51,11 +51,11 @@ async function readFile(fileName: string): Promise { メモリリーク以外のリソースリークでも、システムパフォーマンスの低下やクラッシュといった問題が発生する可能性があります。 -リソースの使用後には必ず解放を行いところですが、解放し忘れてしまう場合もあるでしょう。GCがメモリ解放を自動的に行ってくれるように、非メモリリソースの解放も自動的に行ってくれたら楽になるでしょう。 +リソースの使用後には必ず解放を行いたいところですが、解放し忘れてしまう場合もあるでしょう。GCがメモリ解放を自動的に行ってくれるように、非メモリリソースの解放も自動的に行ってくれたら楽になるでしょう。 ## usingの登場 -そこで、 using宣言が現れました。using宣言で宣言された変数に紐づけられたリソースは、その変数がスコープを抜けるときに `Symbol.dispose` で指定されたコールバック関数が呼び出さます。このコールバック処理に記述されたリソースの解放処理が自動的に実行されます。 +そこで、 using宣言が現れました。using宣言で宣言された変数に紐づけられたリソースは、その変数がスコープを抜けるときに `Symbol.dispose` で指定されたメソッドが呼び出されます。このメソッドに記述されたリソースの解放処理が自動的に実行されます。 ```ts { From 12a061d3c985f716d0160b047e8d5396c3acf5d4 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:21:19 +0900 Subject: [PATCH 08/31] =?UTF-8?q?=E5=BC=95=E6=95=B0=E3=81=8C=E6=8A=9C?= =?UTF-8?q?=E3=81=91=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index eb8f0815..a9cec095 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,7 +4,7 @@ sidebar_label: using宣言 # 新しい変数宣言 using -using宣言(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage2の機能です。TypeScriptでは5.2からサポートされています。 +using宣言(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage3の機能です。TypeScriptでは5.2からサポートされています。 using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで明示的なリソース管理(Explicit Resource Management)を実現できます。 @@ -60,11 +60,11 @@ async function readFile(fileName: string): Promise { ```ts { // 変数初期化によるリソースの確保 - using file = Deno.openSync(); + using file = Deno.openSync(fileName); - file.writeSync(); + file.writeSync(data); - file.readSync(); + file.readSync(buffer); } // スコープを抜けると自動的にfileに紐づくリソースの解放処理が呼ばれる ``` From 127b7529aaa69fea0311fd1d3479e5caa22cee38 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 27 Feb 2026 20:17:45 +0900 Subject: [PATCH 09/31] =?UTF-8?q?C#=20=E3=81=AEusing=E3=81=AB=E3=81=A4?= =?UTF-8?q?=E3=81=84=E3=81=A6=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index a9cec095..be2ffc42 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -88,11 +88,20 @@ JavaScriptの `using` に似ているのがC#の `using` です。以下のよ using(var connection = new SqlConnection(connectionString)) { // ... -} +} // スコープを抜けるときに自動的にDisposeが呼ばれる ``` `IDisposable` インターフェースを実装していることで、スコープ脱出時に、`IDisposable`インターフェースの `Dispose` メソッドによるリソース解放が行われます。 +さらに C# 8.0以降では、JavaScriptの `using` とより似た宣言形式も使えます。 + +```cs +{ + using var connection = new SqlConnection(connectionString); + // ... +} // スコープを抜けるときに自動的にDisposeが呼ばれる +``` + ### Rustのdropメソッド RustもRAIIパターンを採用しており、所有権という概念のもとで、メモリを含むあらゆるリソースの解放タイミングを スコープの脱出時に定めており、コードの構造によって解放のタイミングが決定されます。これによって、リソースリークを静的に防ぎ安全性を担保します。 From 7c52fd36209915e65d1ae93e6d0d5697b7e8dc4f Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 18 Apr 2026 18:55:48 +0900 Subject: [PATCH 10/31] =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index be2ffc42..8de55346 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -6,11 +6,11 @@ sidebar_label: using宣言 using宣言(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage3の機能です。TypeScriptでは5.2からサポートされています。 -using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで明示的なリソース管理(Explicit Resource Management)を実現できます。 +using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで「**明示的なリソース管理** (Explicit Resource Management)」を実現できます。 ## リソースとは -using宣言を理解するための前提として「リソース」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 +using宣言を理解するための前提として「**リソース**」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 - ファイル(具体的にはファイルハンドル) - ネットワーク接続(ネットワークソケット) @@ -19,7 +19,7 @@ using宣言を理解するための前提として「リソース」の概念を JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 -メモリ領域以外のリソースの管理はGCは行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 +メモリ領域以外のリソースの管理はGCは行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 ```ts async function readFile(fileName: string): Promise { @@ -41,7 +41,7 @@ async function readFile(fileName: string): Promise { ## リソースリークとは -「リソースリーク」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。例えば、メモリ解放を忘れた場合には「メモリリーク」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 +「**リソースリーク** (Resource leak)」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。例えば、メモリ解放を忘れた場合には「**メモリリーク** (Memory leak)」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 以下のようにリソースの種類により、リークの問題は呼称が異なりますが、一般にはリソースリークと呼ばれます。 @@ -76,7 +76,7 @@ async function readFile(fileName: string): Promise { ### RAIIパターン -RAII(Resource Acquisition Is Initialization)パターンとは、文字通り「リソース取得は初期化」を意味しており、リソースの確保と解放を変数の初期化と破棄に結びつけるというプログラミングパターンを表します。 +**RAII**(Resource Acquisition Is Initialization)パターンとは、文字通り「リソース取得は初期化」を意味しており、リソースの確保と解放を変数の初期化と破棄に結びつけるというプログラミングパターンを表します。 JavaScriptの `using` を含め、以下に挙げるようなプログラミング言語では類似のRAIIパターンを採用しています。 From 96477325abd59fa3a7bb7753afc211186fa873f7 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:03:36 +0900 Subject: [PATCH 11/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20Deno=E3=81=AE?= =?UTF-8?q?=E8=A3=9C=E8=B6=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 8de55346..5b58c8b8 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -8,6 +8,13 @@ using宣言(using declaration)とは、JavaScriptに導入される新しい変 using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで「**明示的なリソース管理** (Explicit Resource Management)」を実現できます。 +:::info Denoを使う理由 +このページでは以下の理由から [Deno](https://deno.com) ランタイムのファイル API をサンプルコードに多用しています。 + +1. **`Symbol.dispose` が標準で実装済み**: Deno の `FsFile` は `using` 宣言がそのまま使えるオブジェクトの実例です。 +2. **リソースの概念が直感的**: ファイルハンドルやネットワーク接続は、ブラウザの Web API よりもコンピュータのリソース管理に近く、「開いたら閉じる」というライフサイクルが分かりやすいです。 +::: + ## リソースとは using宣言を理解するための前提として「**リソース**」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 @@ -37,6 +44,17 @@ async function readFile(fileName: string): Promise { } ``` +:::info +[`Deno.open`](https://docs.deno.com/api/deno/~/Deno.open) は Deno ランタイムを利用した環境で利用できるファイルを開くためのAPIです。以下のような型を持ちます。 + +```ts +open( + path: string | URL, + options?: OpenOptions, +): Promise +``` +::: + メモリやファイルといったリソースは利用後に必ず解放する必要があります。この解放処理を忘れると、リソースリークという問題が発生します。 ## リソースリークとは From eb1800a3646ec167500bdee4a033076962ae7503 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:04:36 +0900 Subject: [PATCH 12/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=96=87?= =?UTF-8?q?=E7=AB=A0=E3=82=92=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 5b58c8b8..e5940c52 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -17,16 +17,16 @@ using宣言された変数がスコープを抜けるときに、その変数に ## リソースとは -using宣言を理解するための前提として「**リソース**」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 +using宣言を理解するための前提として「**リソース** (resource)」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 - ファイル(具体的にはファイルハンドル) - ネットワーク接続(ネットワークソケット) - DB接続(データベースコネクション) - メモリ領域 -JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 +JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語やZig言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 -メモリ領域以外のリソースの管理はGCは行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 +GCはメモリ領域以外のリソースの管理は行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 ```ts async function readFile(fileName: string): Promise { @@ -69,7 +69,7 @@ open( メモリリーク以外のリソースリークでも、システムパフォーマンスの低下やクラッシュといった問題が発生する可能性があります。 -リソースの使用後には必ず解放を行いたいところですが、解放し忘れてしまう場合もあるでしょう。GCがメモリ解放を自動的に行ってくれるように、非メモリリソースの解放も自動的に行ってくれたら楽になるでしょう。 +リソースの使用後には必ず解放を行いたいところですが、手動で書かなければいけない場合には解放し忘れてしまう場合もあるでしょう。GCがメモリ解放を自動的に行ってくれるように、非メモリリソースの解放も自動的に行ってくれたら楽になることが想像できますね。 ## usingの登場 @@ -83,12 +83,12 @@ open( file.writeSync(data); file.readSync(buffer); -} // スコープを抜けると自動的にfileに紐づくリソースの解放処理が呼ばれる +} // スコープを抜けると自動的に `file` に紐づくリソースの解放処理が呼ばれる ``` スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。 -実は、このようなパターンはRAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 +実は、このようなパターンは後ほど詳しく解説しますが、RAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 ## 他の言語でのパターン From e0dde2e6f535e27d24b47c02fb30c38f91c24738 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:06:08 +0900 Subject: [PATCH 13/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E3=82=B5?= =?UTF-8?q?=E3=83=B3=E3=83=97=E3=83=AB=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92?= =?UTF-8?q?=E3=82=88=E3=82=8A=E5=85=85=E5=AE=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index e5940c52..ec1d627f 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -28,19 +28,30 @@ JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環 GCはメモリ領域以外のリソースの管理は行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 -```ts +```ts twoslash {2-3,9-12} title="resource.ts" +// @noErrors +declare namespace Deno { + interface OpenOptions { read?: boolean; write?: boolean } + interface FsFile { + read(p: Uint8Array): Promise; + close(): void; + [Symbol.dispose](): void; + } + function open(path: string | URL, options?: OpenOptions): Promise; +} +// ---cut--- async function readFile(fileName: string): Promise { - // ファイルを開く - const file = await Deno.open(fileName); - try { - // ファイルを読み取る - const buffer = new Uint8Array(5); - const bytesRead = await file.read(buffer); - console.log(bytesRead); - } finally { - // 必ずファイルを閉じる(リソースを解放) - file.close(); - } + // ファイルを開く + const file = await Deno.open(fileName); + try { + // ファイルを読み取る + const buffer = new Uint8Array(5); + const bytesRead = await file.read(buffer); + console.log(bytesRead); + } finally { + // 必ずファイルを閉じる(リソースを解放) + file.close(); + } } ``` @@ -86,7 +97,29 @@ open( } // スコープを抜けると自動的に `file` に紐づくリソースの解放処理が呼ばれる ``` -スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。 +スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。この `using` 宣言を使うことで先程の `resource.ts` は以下のように書き換えることができます。 + +```ts twoslash title="resource.ts" +declare namespace Deno { + interface OpenOptions { read?: boolean; write?: boolean } + interface FsFile { + read(p: Uint8Array): Promise; + close(): void; + [Symbol.dispose](): void; + } + function open(path: string | URL, options?: OpenOptions): Promise; +} +// ---cut--- +async function readFile(fileName: string): Promise { + // ファイルを開く + using file = await Deno.open(fileName); + // ファイルを読み取る + const buffer = new Uint8Array(5); + const bytesRead = await file.read(buffer); + console.log(bytesRead); +} +``` + 実は、このようなパターンは後ほど詳しく解説しますが、RAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 From e0816c7e4b3a225f154f626975843bbac1c3eb06 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:08:30 +0900 Subject: [PATCH 14/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20Disposable?= =?UTF-8?q?=E3=81=A8Symbol.dispose=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6?= =?UTF-8?q?=E3=81=AE=E8=AA=AC=E6=98=8E=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index ec1d627f..4aa485a8 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -120,6 +120,25 @@ async function readFile(fileName: string): Promise { } ``` +### DisposableとSymbol.dispose + +`using` 宣言で使えるオブジェクトは、`Disposable` インターフェースを実装している、つまり `[Symbol.dispose]()` メソッドを持つ必要があります。 + +```ts twoslash {1, 4-6, 11} +const getConnection = (host: string): Disposable => { + console.log(`接続を開く: ${host}`); + return { + [Symbol.dispose]() { + console.log(`接続を閉じる: ${host}`); + }, + }; +}; + +{ + using connection = getConnection("localhost"); + // ... +} // ここで自動的に「接続を閉じる: localhost」が出力される +``` 実は、このようなパターンは後ほど詳しく解説しますが、RAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 From 9f6b668c16e5c1c05d1d2b33c0bdc9105c4bb3a1 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:08:54 +0900 Subject: [PATCH 15/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20await=20using?= =?UTF-8?q?=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E3=82=82=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 4aa485a8..4ba420d4 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -142,6 +142,41 @@ const getConnection = (host: string): Disposable => { 実は、このようなパターンは後ほど詳しく解説しますが、RAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 +### await using + +クリーンアップ処理自体が非同期の場合には、`await using` 宣言を使います。`await using` はスコープ脱出時に `[Symbol.asyncDispose]()` を `await` して呼び出します。 + +`AsyncDisposable` インターフェースを実装したオブジェクトが対象です。 + +```ts twoslash {1, 4-8, 13} +const getConnection = (host: string): AsyncDisposable => { + console.log(`接続を開く: ${host}`); + return { + async [Symbol.asyncDispose]() { + // 非同期のクリーンアップ処理(例: ネットワーク越しの切断) + await Promise.resolve(); + console.log(`接続を閉じる: ${host}`); + }, + }; +}; + +{ + await using connection = getConnection("localhost"); + // ... +} // ここで非同期の「接続を閉じる: localhost」が await される +// ---cut-after--- +export {}; +``` + +`using` と `await using` の使い分けは次のとおりです。 + +| 宣言 | 対応インターフェース | クリーンアップ | +| --- | --- | --- | +| `using` | `Disposable` (`Symbol.dispose`) | 同期 | +| `await using` | `AsyncDisposable` (`Symbol.asyncDispose`) | 非同期 | + +なお、`await using` は `async` 関数またはトップレベル `await` が使える環境でのみ利用できます。 + ## 他の言語でのパターン ### RAIIパターン From 26a613013792cf740fbf0ce3da149cd31087e50d Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:10:20 +0900 Subject: [PATCH 16/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20Csharp?= =?UTF-8?q?=E3=81=AE=E8=AA=AC=E6=98=8E=E3=82=92=E5=BC=B7=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 4ba420d4..a9120c87 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -187,10 +187,42 @@ JavaScriptの `using` を含め、以下に挙げるようなプログラミン ### C#のusing句 -JavaScriptの `using` に似ているのがC#の `using` です。以下のように `using` 句に指定されたオブジェクト(`SqlConnection`)は `IDisposable` インターフェースを実装している必要があります。 +JavaScriptの `using` に似ているのがC#の `using` です。`using` 句に指定されたオブジェクトは `IDisposable` インターフェースを実装している必要があります。 -```cs -using(var connection = new SqlConnection(connectionString)) +`IDisposable` インターフェースは `Dispose` メソッドを持ちます。 + +```csharp +public interface IDisposable +{ + void Dispose(); +} +``` + +実装例として、DB接続クラスに `IDisposable` を実装すると以下のようになります。 + +```csharp +class Connection : IDisposable +{ + private readonly string host; + + public Connection(string host) + { + this.host = host; + Console.WriteLine($"接続を開く: {host}"); + } + + public void Dispose() + { + // スコープを抜けるときに自動的に呼ばれる + Console.WriteLine($"接続を閉じる: {host}"); + } +} +``` + +この `Connection` クラスを `using` 句で使うと、スコープ脱出時に自動的に `Dispose` が呼ばれます。 + +```csharp title="C#のusing句" +using(var connection = new Connection("localhost")) { // ... } // スコープを抜けるときに自動的にDisposeが呼ばれる @@ -198,11 +230,11 @@ using(var connection = new SqlConnection(connectionString)) `IDisposable` インターフェースを実装していることで、スコープ脱出時に、`IDisposable`インターフェースの `Dispose` メソッドによるリソース解放が行われます。 -さらに C# 8.0以降では、JavaScriptの `using` とより似た宣言形式も使えます。 +C# 8.0以降では、JavaScriptの `using` により似ている以下のような宣言形式も使えます。 -```cs +```csharp title="C#のusing var" { - using var connection = new SqlConnection(connectionString); + using var connection = new Connection("localhost"); // ... } // スコープを抜けるときに自動的にDisposeが呼ばれる ``` From ec169136069236cef22517d7de6d733c85242f8c Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:10:43 +0900 Subject: [PATCH 17/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20C=E8=A8=80?= =?UTF-8?q?=E8=AA=9E=E3=81=AE=E6=98=8E=E7=A4=BA=E7=9A=84=E3=81=AA=E3=83=A1?= =?UTF-8?q?=E3=83=A2=E3=83=AA=E8=A7=A3=E6=94=BE=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index a9120c87..87002521 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -26,6 +26,22 @@ using宣言を理解するための前提として「**リソース** (resource) JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語やZig言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 +```c title="C言語の明示的なメモリ解放" +#include + +int main(void) { + // メモリを確保 + int *array = malloc(5 * sizeof(int)); + + array[0] = 42; + + // 明示的にメモリを解放しなければならない + free(array); + + return 0; +} +``` + GCはメモリ領域以外のリソースの管理は行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 ```ts twoslash {2-3,9-12} title="resource.ts" From 3a2056db7a7f360b605fb2fe33fc923a6866362e Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:11:09 +0900 Subject: [PATCH 18/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20Rust=E3=81=AEd?= =?UTF-8?q?rop=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89=E3=81=AB=E3=81=A4?= =?UTF-8?q?=E3=81=84=E3=81=A6=E3=81=AE=E8=AA=AC=E6=98=8E=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 87002521..ec5e2527 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -257,8 +257,38 @@ C# 8.0以降では、JavaScriptの `using` により似ている以下のよう ### Rustのdropメソッド -RustもRAIIパターンを採用しており、所有権という概念のもとで、メモリを含むあらゆるリソースの解放タイミングを スコープの脱出時に定めており、コードの構造によって解放のタイミングが決定されます。これによって、リソースリークを静的に防ぎ安全性を担保します。 +RustもRAIIパターンを採用しており、所有権という概念のもとで、メモリを含むあらゆるリソースの解放タイミングを**スコープの脱出時**に定めており、**コードの構造によって解放のタイミングが決定されます**。これによって、リソースリークを静的に防ぎ安全性を担保します。 このような所有権に基づいたリソース管理はまさに、RAIIに基づいたリソース管理の方法となっています。 Rustの `Drop` トレイトに存在する `drop` というメソッドがこれを実現しています。オブジェクトがスコープを抜けるときにはこのメソッドが自動的に呼び出されて、登録されているリソース解放の処理を行います。 + +```rust title="Rustのdropメソッド" +struct Connection { + host: String, +} + +impl Connection { + fn new(host: &str) -> Self { + println!("接続を開く: {}", host); + Connection { host: host.to_string() } + } +} + +impl Drop for Connection { + fn drop(&mut self) { + // スコープを抜けるときに自動的に呼ばれる + println!("接続を閉じる: {}", self.host); + } +} + +fn main() { + { + let connection = Connection::new("localhost"); + // ... + } // ここで自動的に「接続を閉じる: localhost」が出力される +} +``` + +Rustでは `using` のような特別な宣言は不要で、すべての変数がデフォルトでRAIIの対象となります。 + From 80e80602ad46d79110105f17b6b961410af5acc4 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:12:42 +0900 Subject: [PATCH 19/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E5=90=84?= =?UTF-8?q?=E8=A8=80=E8=AA=9E=E3=81=A7=E3=81=AE=E6=AF=94=E8=BC=83=E8=A1=A8?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index ec5e2527..06d464ae 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -292,3 +292,15 @@ fn main() { Rustでは `using` のような特別な宣言は不要で、すべての変数がデフォルトでRAIIの対象となります。 +## 各言語のRAIIパターン比較 + +TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとおりです。 + +| 比較項目 | TypeScript | C# | Rust | +| --- | --- | --- | --- | +| インターフェース/トレイト | `Disposable` | `IDisposable` | `Drop` | +| クリーンアップメソッド | `[Symbol.dispose]()` | `Dispose()` | `drop(&mut self)` | +| 宣言構文 | `using` / `await using` | `using` 句 / `using var` | 不要(暗黙) | +| 強制力 | オプトイン(明示的に `using` が必要) | オプトイン(明示的に `using` が必要) | すべての変数が対象 | + +大きな違いは**強制力**にあります。TypeScriptとC#では `using` / `using var` を書かなければRAIIは機能せず、うっかり書き忘れるとリソースリークが起きます。一方Rustでは所有権システムにより、すべての変数がスコープ脱出時に自動的に `drop` される仕組みになっており、書き忘れが原理的に発生しません。 From e9be21e4aeff321ca8a594f77f10b5840a6c6372 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:19:58 +0900 Subject: [PATCH 20/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E5=BE=AE?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 06d464ae..5afdc57b 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -229,7 +229,6 @@ class Connection : IDisposable public void Dispose() { - // スコープを抜けるときに自動的に呼ばれる Console.WriteLine($"接続を閉じる: {host}"); } } @@ -240,7 +239,7 @@ class Connection : IDisposable ```csharp title="C#のusing句" using(var connection = new Connection("localhost")) { - // ... + // ... } // スコープを抜けるときに自動的にDisposeが呼ばれる ``` From bbd9063234ede6ef06158cbcacf3192345d9590f Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:33:11 +0900 Subject: [PATCH 21/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=9B=B8?= =?UTF-8?q?=E3=81=8D=E5=87=BA=E3=81=97=E3=82=92=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 5afdc57b..2d5fcad1 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,7 +4,11 @@ sidebar_label: using宣言 # 新しい変数宣言 using -using宣言(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage3の機能です。TypeScriptでは5.2からサポートされています。 +[変数宣言: letとconst](reference/values-types-variables/let-and-const.md) + +この章の最初のページで`let`と`const`という変数宣言について学びました。 + +**using宣言**(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage3の機能です。TypeScriptでは5.2からサポートされています。 using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで「**明示的なリソース管理** (Explicit Resource Management)」を実現できます。 From 0be81dbdff363ec5cff1cd90adf347df007831d2 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:36:29 +0900 Subject: [PATCH 22/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20await=20using?= =?UTF-8?q?=20=E3=81=AE=E7=AE=87=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 2d5fcad1..883f80b6 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -166,7 +166,7 @@ const getConnection = (host: string): Disposable => { クリーンアップ処理自体が非同期の場合には、`await using` 宣言を使います。`await using` はスコープ脱出時に `[Symbol.asyncDispose]()` を `await` して呼び出します。 -`AsyncDisposable` インターフェースを実装したオブジェクトが対象です。 +`await using` は `AsyncDisposable` インターフェースを実装したオブジェクトが対象となります。 ```ts twoslash {1, 4-8, 13} const getConnection = (host: string): AsyncDisposable => { @@ -188,12 +188,14 @@ const getConnection = (host: string): AsyncDisposable => { export {}; ``` +ただし、`await using` はスコープ脱出時にまず `[Symbol.asyncDispose]()` を探し、なければ `[Symbol.dispose]()` にフォールバックします。そのため `AsyncDisposable` だけでなく `Disposable` を実装したオブジェクトにも使えます。 + `using` と `await using` の使い分けは次のとおりです。 | 宣言 | 対応インターフェース | クリーンアップ | | --- | --- | --- | | `using` | `Disposable` (`Symbol.dispose`) | 同期 | -| `await using` | `AsyncDisposable` (`Symbol.asyncDispose`) | 非同期 | +| `await using` | `AsyncDisposable` (`Symbol.asyncDispose`) を優先、なければ `Disposable` (`Symbol.dispose`) にフォールバック | 非同期(フォールバック時は同期) | なお、`await using` は `async` 関数またはトップレベル `await` が使える環境でのみ利用できます。 From c7a1215867074140d494065ddb97db38c568cda8 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Fri, 8 May 2026 20:48:00 +0900 Subject: [PATCH 23/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20using=E5=AE=A3?= =?UTF-8?q?=E8=A8=80=E3=81=AE=E5=9F=BA=E6=9C=AC=E6=80=A7=E8=B3=AA=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 883f80b6..fdeb4e8a 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -160,7 +160,24 @@ const getConnection = (host: string): Disposable => { } // ここで自動的に「接続を閉じる: localhost」が出力される ``` +:::info RAIIパターン 実は、このようなパターンは後ほど詳しく解説しますが、RAII(Resource Acquisition is Initialization)パターンと呼ばれ、他のプログラミング言語にも同様のパターンを見ることができます。 +::: + +なお、`using` を使って宣言した変数は `const` 宣言による変数と同様にブロックスコープの変数として宣言され、再代入を行なうことができません。 +また、`using` 宣言した変数の初期化として使える値は `null`、`undefined` または上述した `Disposable` インターフェースを実装したオブジェクトのみとなります。 + +```ts twoslash +using t1 = null; +using t2 = undefined; +using t3 = { + [Symbol.dispose]() { + }, +}; + +// @errors: 2850 +using t4 = 1; +``` ### await using From 658ae3970d78ac0b98e6312838a293a6f1f4b6b0 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:20:52 +0900 Subject: [PATCH 24/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E3=82=B5?= =?UTF-8?q?=E3=83=B3=E3=83=97=E3=83=AB=E3=82=B3=E3=83=BC=E3=83=89=E3=81=AE?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index fdeb4e8a..0688b5ba 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -230,7 +230,7 @@ JavaScriptの `using` に似ているのがC#の `using` です。`using` 句に `IDisposable` インターフェースは `Dispose` メソッドを持ちます。 -```csharp +```csharp title="C#のIDisposableインターフェース" public interface IDisposable { void Dispose(); @@ -239,7 +239,7 @@ public interface IDisposable 実装例として、DB接続クラスに `IDisposable` を実装すると以下のようになります。 -```csharp +```csharp title="C#のIDisposableインターフェースの実装" class Connection : IDisposable { private readonly string host; From 1711494ef7ec8a8a3ed89a6be8d9e0aa602f25eb Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:21:43 +0900 Subject: [PATCH 25/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E8=A1=A8?= =?UTF-8?q?=E7=8F=BE=E3=81=AA=E3=81=A9=E6=B0=97=E3=81=AB=E3=81=AA=E3=82=8B?= =?UTF-8?q?=E7=AE=87=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 0688b5ba..2aed40a7 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -4,9 +4,7 @@ sidebar_label: using宣言 # 新しい変数宣言 using -[変数宣言: letとconst](reference/values-types-variables/let-and-const.md) - -この章の最初のページで`let`と`const`という変数宣言について学びました。 +この章の最初のページで[`let`と`const`](reference/values-types-variables/let-and-const.md)という変数宣言について学びました。 **using宣言**(using declaration)とは、JavaScriptに導入される新しい変数宣言であり、執筆時点のECMAScriptプロポーザルではStage3の機能です。TypeScriptでは5.2からサポートされています。 @@ -104,7 +102,7 @@ open( ## usingの登場 -そこで、 using宣言が現れました。using宣言で宣言された変数に紐づけられたリソースは、その変数がスコープを抜けるときに `Symbol.dispose` で指定されたメソッドが呼び出されます。このメソッドに記述されたリソースの解放処理が自動的に実行されます。 +そこでusing宣言が登場しました。using宣言で宣言された変数に紐づけられたリソースは、その変数がスコープを抜けるときに `[Symbol.dispose]()` メソッドが呼び出され、リソースの解放処理が自動的に実行されます。 ```ts { @@ -325,4 +323,4 @@ TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとお | 宣言構文 | `using` / `await using` | `using` 句 / `using var` | 不要(暗黙) | | 強制力 | オプトイン(明示的に `using` が必要) | オプトイン(明示的に `using` が必要) | すべての変数が対象 | -大きな違いは**強制力**にあります。TypeScriptとC#では `using` / `using var` を書かなければRAIIは機能せず、うっかり書き忘れるとリソースリークが起きます。一方Rustでは所有権システムにより、すべての変数がスコープ脱出時に自動的に `drop` される仕組みになっており、書き忘れが原理的に発生しません。 +3者間の大きな違いは**強制力**にあります。TypeScriptとC#では `using` を書かなければRAIIは機能せず、うっかり書き忘れるとリソースリークが起きます。一方Rustでは所有権システムにより、すべての変数がスコープ脱出時に自動的に `drop` される仕組みになっており、書き忘れが原理的に発生しません。 From a7ed670797ccacc8d236a1fdcdd8dbd1d0bbf79c Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:38:27 +0900 Subject: [PATCH 26/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20Rust=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=82=92=E3=82=88=E3=82=8A=E6=AD=A3=E7=A2=BA?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 2aed40a7..91490c25 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -279,9 +279,9 @@ C# 8.0以降では、JavaScriptの `using` により似ている以下のよう RustもRAIIパターンを採用しており、所有権という概念のもとで、メモリを含むあらゆるリソースの解放タイミングを**スコープの脱出時**に定めており、**コードの構造によって解放のタイミングが決定されます**。これによって、リソースリークを静的に防ぎ安全性を担保します。 -このような所有権に基づいたリソース管理はまさに、RAIIに基づいたリソース管理の方法となっています。 +いわゆる「所有権」とは、リソースの管理責任であり、所有者となる変数はこの所有権を持ち、所有権を移動したり、値の複製で新たな所有権を生成することが可能で、所有権を持つ変数がスコープを脱出したときに、リソースの解放処理が呼び出されることになります。このような所有権に基づいたリソース管理はまさに、RAIIに基づいたリソース管理の方法となっています。 -Rustの `Drop` トレイトに存在する `drop` というメソッドがこれを実現しています。オブジェクトがスコープを抜けるときにはこのメソッドが自動的に呼び出されて、登録されているリソース解放の処理を行います。 +非メモリリソースについてのスコープ脱出時の自動解放を実現しているのが、Rustの `Drop` トレイトに存在する `drop` というメソッドです。変数がスコープを抜けるときにはこのメソッドが自動的に呼び出されて、実装されているリソース解放の処理を行います。 ```rust title="Rustのdropメソッド" struct Connection { @@ -312,6 +312,10 @@ fn main() { Rustでは `using` のような特別な宣言は不要で、すべての変数がデフォルトでRAIIの対象となります。 +なお、メモリリソースの解放はこの `drop()` の実装とは関係なく、コンパイラがコンパイル時にスコープ脱出時のタイミングに解放処理を差し込みます。これによって、基本的にすべてのリソースの解放がスコープ脱出時として定められます。 + +TypeScriptやC#は実行時にどのオブジェクトが不要であるかをGCが判定して動的に解放しますが、Rustではコンパイル時にコードの構造によって静的に決定された解放タイミングにより解放処理が発生するようなコードが生成されます。 + ## 各言語のRAIIパターン比較 TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとおりです。 From c12525cd7ddd8723ff681c08c1a18e6d62e1ff26 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:38:56 +0900 Subject: [PATCH 27/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E3=83=A1?= =?UTF-8?q?=E3=83=A2=E3=83=AA=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=82=92=E8=A9=B3=E7=B4=B0=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 91490c25..6f2e4bac 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -19,12 +19,18 @@ using宣言された変数がスコープを抜けるときに、その変数に ## リソースとは -using宣言を理解するための前提として「**リソース** (resource)」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、以下のようなコンポーネントのことを指します。 +using宣言を理解するための前提として「**リソース** (resource)」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、簡単に言えば、プログラムがOSから借りて使うものであり、使い終わったら必ず返す必要のあるコンポーネントのことで、例えば以下のようなものを指します。 -- ファイル(具体的にはファイルハンドル) +- ファイル(ファイルハンドル) - ネットワーク接続(ネットワークソケット) - DB接続(データベースコネクション) -- メモリ領域 +- メモリ領域(ヒープメモリ) + +:::caution +このページでの「メモリ」とは「**ヒープメモリ**」のことを指していることに注意してください。「**スタックメモリ**」はGCとは関係なく解放されます。これらのメモリの違いについての詳細は以下のページなどを参照してください。 + +https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html +::: JavaScript/TypeScriptの文脈において、特にメモリ領域は実行環境が持つGC(ガベージコレクタ)により自動的に管理されます。そのためC言語やZig言語のようにプログラマーが明示的なメモリ解放を行なう必要がありません。 @@ -44,7 +50,7 @@ int main(void) { } ``` -GCはメモリ領域以外のリソースの管理は行わないため、非メモリリソースの管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 +GCはメモリ領域以外のリソースの管理は行わないため、ファイルやネットワークソケットといった**非メモリリソース**の管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 ```ts twoslash {2-3,9-12} title="resource.ts" // @noErrors From 8a6a0daafa102aa4e484bbac454c8dc5ae0c4c78 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:39:54 +0900 Subject: [PATCH 28/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=98=8E?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E3=81=AA=E3=83=AA=E3=82=BD=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 6f2e4bac..62d4862a 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -141,9 +141,11 @@ async function readFile(fileName: string): Promise { const buffer = new Uint8Array(5); const bytesRead = await file.read(buffer); console.log(bytesRead); -} +} // スコープ脱出時に自動的にリソース解放 ``` +冒頭で使った「明示的なリソース管理」とは、このようにusing宣言で定義された変数に紐づくリソースの解放タイミング、ひいてはライフタイム(生存期間)そのものを、スコープというコードの構造によって明確に表すことができるということです。つまり、`using` が付いていることでリソース解放タイミングが誰が見ても一目でわかるようになっています。 + ### DisposableとSymbol.dispose `using` 宣言で使えるオブジェクトは、`Disposable` インターフェースを実装している、つまり `[Symbol.dispose]()` メソッドを持つ必要があります。 From 46a12b00ab96a092bf11357914c384cfd01dbf43 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sat, 9 May 2026 14:50:35 +0900 Subject: [PATCH 29/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20=E6=B7=B7?= =?UTF-8?q?=E4=B9=B1=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AA=E6=96=87?= =?UTF-8?q?=E7=AB=A0=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/reference/values-types-variables/using.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index 62d4862a..d3e8e9dd 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -322,8 +322,6 @@ Rustでは `using` のような特別な宣言は不要で、すべての変数 なお、メモリリソースの解放はこの `drop()` の実装とは関係なく、コンパイラがコンパイル時にスコープ脱出時のタイミングに解放処理を差し込みます。これによって、基本的にすべてのリソースの解放がスコープ脱出時として定められます。 -TypeScriptやC#は実行時にどのオブジェクトが不要であるかをGCが判定して動的に解放しますが、Rustではコンパイル時にコードの構造によって静的に決定された解放タイミングにより解放処理が発生するようなコードが生成されます。 - ## 各言語のRAIIパターン比較 TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとおりです。 From 305ae5769bf4bade81725c8a2cce9991fedf1457 Mon Sep 17 00:00:00 2001 From: yo-goto <50942816+yo-goto@users.noreply.github.com> Date: Sun, 10 May 2026 14:31:45 +0900 Subject: [PATCH 30/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20format?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index d3e8e9dd..bf9adfa2 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -15,6 +15,7 @@ using宣言された変数がスコープを抜けるときに、その変数に 1. **`Symbol.dispose` が標準で実装済み**: Deno の `FsFile` は `using` 宣言がそのまま使えるオブジェクトの実例です。 2. **リソースの概念が直感的**: ファイルハンドルやネットワーク接続は、ブラウザの Web API よりもコンピュータのリソース管理に近く、「開いたら閉じる」というライフサイクルが分かりやすいです。 + ::: ## リソースとは @@ -55,7 +56,10 @@ GCはメモリ領域以外のリソースの管理は行わないため、ファ ```ts twoslash {2-3,9-12} title="resource.ts" // @noErrors declare namespace Deno { - interface OpenOptions { read?: boolean; write?: boolean } + interface OpenOptions { + read?: boolean; + write?: boolean; + } interface FsFile { read(p: Uint8Array): Promise; close(): void; @@ -88,6 +92,7 @@ open( options?: OpenOptions, ): Promise ``` + ::: メモリやファイルといったリソースは利用後に必ず解放する必要があります。この解放処理を忘れると、リソースリークという問題が発生します。 @@ -125,7 +130,10 @@ open( ```ts twoslash title="resource.ts" declare namespace Deno { - interface OpenOptions { read?: boolean; write?: boolean } + interface OpenOptions { + read?: boolean; + write?: boolean; + } interface FsFile { read(p: Uint8Array): Promise; close(): void; @@ -177,8 +185,7 @@ const getConnection = (host: string): Disposable => { using t1 = null; using t2 = undefined; using t3 = { - [Symbol.dispose]() { - }, + [Symbol.dispose]() {}, }; // @errors: 2850 @@ -215,9 +222,9 @@ export {}; `using` と `await using` の使い分けは次のとおりです。 -| 宣言 | 対応インターフェース | クリーンアップ | -| --- | --- | --- | -| `using` | `Disposable` (`Symbol.dispose`) | 同期 | +| 宣言 | 対応インターフェース | クリーンアップ | +| ------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------- | +| `using` | `Disposable` (`Symbol.dispose`) | 同期 | | `await using` | `AsyncDisposable` (`Symbol.asyncDispose`) を優先、なければ `Disposable` (`Symbol.dispose`) にフォールバック | 非同期(フォールバック時は同期) | なお、`await using` は `async` 関数またはトップレベル `await` が使える環境でのみ利用できます。 @@ -326,11 +333,11 @@ Rustでは `using` のような特別な宣言は不要で、すべての変数 TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとおりです。 -| 比較項目 | TypeScript | C# | Rust | -| --- | --- | --- | --- | -| インターフェース/トレイト | `Disposable` | `IDisposable` | `Drop` | -| クリーンアップメソッド | `[Symbol.dispose]()` | `Dispose()` | `drop(&mut self)` | -| 宣言構文 | `using` / `await using` | `using` 句 / `using var` | 不要(暗黙) | -| 強制力 | オプトイン(明示的に `using` が必要) | オプトイン(明示的に `using` が必要) | すべての変数が対象 | +| 比較項目 | TypeScript | C# | Rust | +| ------------------------- | ----------------------------------- | ----------------------------------- | ------------------ | +| インターフェース/トレイト | `Disposable` | `IDisposable` | `Drop` | +| クリーンアップメソッド | `[Symbol.dispose]()` | `Dispose()` | `drop(&mut self)` | +| 宣言構文 | `using` / `await using` | `using` 句 / `using var` | 不要(暗黙) | +| 強制力 | オプトイン(明示的に `using` が必要) | オプトイン(明示的に `using` が必要) | すべての変数が対象 | 3者間の大きな違いは**強制力**にあります。TypeScriptとC#では `using` を書かなければRAIIは機能せず、うっかり書き忘れるとリソースリークが起きます。一方Rustでは所有権システムにより、すべての変数がスコープ脱出時に自動的に `drop` される仕組みになっており、書き忘れが原理的に発生しません。 From f8b5488148247562817d2b469cb0a146de3961ce Mon Sep 17 00:00:00 2001 From: suin Date: Fri, 15 May 2026 19:49:57 +0900 Subject: [PATCH 31/31] =?UTF-8?q?using=E5=AE=A3=E8=A8=80:=20textlint?= =?UTF-8?q?=E3=81=AE=E6=8C=87=E6=91=98=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reference/values-types-variables/using.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/reference/values-types-variables/using.md b/docs/reference/values-types-variables/using.md index bf9adfa2..288e13c3 100644 --- a/docs/reference/values-types-variables/using.md +++ b/docs/reference/values-types-variables/using.md @@ -11,7 +11,7 @@ sidebar_label: using宣言 using宣言された変数がスコープを抜けるときに、その変数に紐づくリソースについて自動的にクリーンアップ処理が実行されることで「**明示的なリソース管理** (Explicit Resource Management)」を実現できます。 :::info Denoを使う理由 -このページでは以下の理由から [Deno](https://deno.com) ランタイムのファイル API をサンプルコードに多用しています。 +このページでは次の理由から [Deno](https://deno.com) ランタイムのファイル API をサンプルコードに多用しています。 1. **`Symbol.dispose` が標準で実装済み**: Deno の `FsFile` は `using` 宣言がそのまま使えるオブジェクトの実例です。 2. **リソースの概念が直感的**: ファイルハンドルやネットワーク接続は、ブラウザの Web API よりもコンピュータのリソース管理に近く、「開いたら閉じる」というライフサイクルが分かりやすいです。 @@ -20,7 +20,7 @@ using宣言された変数がスコープを抜けるときに、その変数に ## リソースとは -using宣言を理解するための前提として「**リソース** (resource)」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、簡単に言えば、プログラムがOSから借りて使うものであり、使い終わったら必ず返す必要のあるコンポーネントのことで、例えば以下のようなものを指します。 +using宣言を理解するための前提として「**リソース** (resource)」の概念を知っておく必要があります。リソース、あるいはシステムリソースとは、簡単に言えば、プログラムがOSから借りて使うものであり、使い終わったら必ず返す必要のあるコンポーネントのことで、たとえば次のようなものを指します。 - ファイル(ファイルハンドル) - ネットワーク接続(ネットワークソケット) @@ -28,7 +28,7 @@ using宣言を理解するための前提として「**リソース** (resource) - メモリ領域(ヒープメモリ) :::caution -このページでの「メモリ」とは「**ヒープメモリ**」のことを指していることに注意してください。「**スタックメモリ**」はGCとは関係なく解放されます。これらのメモリの違いについての詳細は以下のページなどを参照してください。 +このページでの「メモリ」とは「**ヒープメモリ**」のことを指していることに注意してください。「**スタックメモリ**」はGCとは関係なく解放されます。これらのメモリの違いについての詳細は次のページなどを参照してください。 https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html ::: @@ -51,7 +51,7 @@ int main(void) { } ``` -GCはメモリ領域以外のリソースの管理は行わないため、ファイルやネットワークソケットといった**非メモリリソース**の管理はプログラマーが明示的に行なう必要があります。例えば、以下の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは以下のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 +GCはメモリ領域以外のリソースの管理は行わないため、ファイルやネットワークソケットといった**非メモリリソース**の管理はプログラマーが明示的に行なう必要があります。たとえば、次の Deno 環境で作成されたファイル読み込みの処理では、ファイルハンドルは次のように読み取りのために `open()` したら、利用終了時には `close()` するという処理を行なう必要があります。 ```ts twoslash {2-3,9-12} title="resource.ts" // @noErrors @@ -84,7 +84,7 @@ async function readFile(fileName: string): Promise { ``` :::info -[`Deno.open`](https://docs.deno.com/api/deno/~/Deno.open) は Deno ランタイムを利用した環境で利用できるファイルを開くためのAPIです。以下のような型を持ちます。 +[`Deno.open`](https://docs.deno.com/api/deno/~/Deno.open) は Deno ランタイムを利用した環境で利用できるファイルを開くためのAPIです。次のような型を持ちます。 ```ts open( @@ -99,9 +99,9 @@ open( ## リソースリークとは -「**リソースリーク** (Resource leak)」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。例えば、メモリ解放を忘れた場合には「**メモリリーク** (Memory leak)」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 +「**リソースリーク** (Resource leak)」とは、リソースの使用後に解放処理を忘れることで、そのリソースが無駄に占有され続ける問題のことです。たとえば、メモリ解放を忘れた場合には「**メモリリーク** (Memory leak)」と呼ばれる問題となり、プログラムの使用したメモリ領域が解放されず残されることでメモリ容量が徐々に減っていってしまいます。 -以下のようにリソースの種類により、リークの問題は呼称が異なりますが、一般にはリソースリークと呼ばれます。 +次のようにリソースの種類により、リークの問題は呼称が異なりますが、一般にはリソースリークと呼ばれます。 - ファイルハンドルリーク - ソケットリーク @@ -126,7 +126,7 @@ open( } // スコープを抜けると自動的に `file` に紐づくリソースの解放処理が呼ばれる ``` -スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。この `using` 宣言を使うことで先程の `resource.ts` は以下のように書き換えることができます。 +スコープ脱出のタイミングでリソース解放が行われる、つまり、コードの構造により自動的にリソースの解放タイミングが決まります。この `using` 宣言を使うことで先ほどの `resource.ts` は次のように書き換えることができます。 ```ts twoslash title="resource.ts" declare namespace Deno { @@ -235,7 +235,7 @@ export {}; **RAII**(Resource Acquisition Is Initialization)パターンとは、文字通り「リソース取得は初期化」を意味しており、リソースの確保と解放を変数の初期化と破棄に結びつけるというプログラミングパターンを表します。 -JavaScriptの `using` を含め、以下に挙げるようなプログラミング言語では類似のRAIIパターンを採用しています。 +JavaScriptの `using` を含め、次に挙げるようなプログラミング言語では類似のRAIIパターンを採用しています。 ### C#のusing句 @@ -250,7 +250,7 @@ public interface IDisposable } ``` -実装例として、DB接続クラスに `IDisposable` を実装すると以下のようになります。 +実装例として、DB接続クラスに `IDisposable` を実装すると次のようになります。 ```csharp title="C#のIDisposableインターフェースの実装" class Connection : IDisposable @@ -281,7 +281,7 @@ using(var connection = new Connection("localhost")) `IDisposable` インターフェースを実装していることで、スコープ脱出時に、`IDisposable`インターフェースの `Dispose` メソッドによるリソース解放が行われます。 -C# 8.0以降では、JavaScriptの `using` により似ている以下のような宣言形式も使えます。 +C# 8.0以降では、JavaScriptの `using` により似ている次のような宣言形式も使えます。 ```csharp title="C#のusing var" { @@ -331,7 +331,7 @@ Rustでは `using` のような特別な宣言は不要で、すべての変数 ## 各言語のRAIIパターン比較 -TypeScript・C#・Rustそれぞれの仕組みを比較すると以下のとおりです。 +TypeScript・C#・Rustそれぞれの仕組みを比較すると次のとおりです。 | 比較項目 | TypeScript | C# | Rust | | ------------------------- | ----------------------------------- | ----------------------------------- | ------------------ |