型推論とは

型推論とは、メソッド内のローカル変数を初期値付きで(右辺がある状態で)宣言する際に、通常の型宣言の代わりに”var”という仮の型を使用できるという文法です。
“var”を用いた際は、コンパイル時に自動で型を判断し、その型への置き換えが行われます。

C#では3.0(2007/11)から導入されており、現在ではお馴染みの文法と言えるでしょう。
Javaでは長らく導入されていませんでしたが、10(2018/03)でついに導入されました。
今後はJavaの案件でも目にすることが増えると思います。

型推論を用いることで、冗長な型宣言をすっきりさせることができます。
C#の例で言うと、下記のコードで、定義時に”List”と型を指定している箇所は、”var”に書き変えることができます。

また、ソース修正で型を変えるような場合にも、”var”と記述した部分は変更する必要がなくなるので、ソース修正が楽になるというメリットもあります。


型はコンパイル時に決まるため、実行時に動的に型が変わることはありません。
例えば、下記のようなコードはコンパイルエラーになります。
((22,20): error CS0029: 型 ‘int’ を型 ‘System.Collections.Generic.List’ に暗黙的に変換できません。)
誤って意図しない型を代入しようとした場合はコンパイル時にエラーとして検知できるので、その意味では安心して使えます。

ちなみに、「型推論」と似た概念として「動的型付け」というものがあるのですが、こちらは途中で異なる型を代入すると変数の型そのものが変わり処理が続行されます。
例えば、JavaScriptでは動的型付けが採用されており、予約語も”var”を用いるため、「型推論」と混同されがちです。
「動的型付け」の方は誤って意図しない型を代入しても実行するまで気付くことができず、実行時に出るエラーが分かりにくいものだったり、そもそもエラーが出ないこともあるので、注意が必要です。


以上のように便利な型推論ですが、可読性を落とすデメリットもあります。
具体的に言うと、変数宣言時の型が一目瞭然ではない場合に用いると可読性を落とします。

例えば、下記のコードで変数宣言時の型を知るためには、”MyFunc”の仕様を知っている必要があります。
“MyFunc”のような独自の関数でなくても、チーム内での知名度が低い関数を用いる場合は注意が必要です。

また、”int”や”string”のような基本的な型に対して用いるのも、元々型宣言が冗長ではないという意味で型推論を使用するメリットが少ないので、他の開発者に違和感を抱かせてしまう可能性があります。


いかがでしたでしょうか?

「型推論」は便利ながらも、「動的型付け」のように実行時エラーを引き起こす原因を作ることはないので、安心して使える文法だと思います。
その使いやすさからJavaでも今後目にする機会が増えると思うので、このような文法があるということは頭に入れておいて損はないと思います。

Javaのバージョンは今でも上がり続けているので、新しい便利な文法があればこれからも紹介したいと思います!

C#:await・asyncの簡単なサンプルコード

C#のawait・asyncは非同期処理のために用意された文法なのですが、Webで調べてみても難しく書かれていることが多く、そもそも何のための処理なのか理解するのが難しい感があります。
await・asyncを用いて関数を呼び出しても、その関数の処理が終わるまで待つという動きをするので、同期処理と何が違うのかいまいちわかりにくいというのもあると思います。
以上のような背景があるので、簡単なサンプルコードを書いてみることとしました。

await・asyncは、GUIアプリのために用意された文法と考えて良いです。
await・asyncを用いない場合、処理中はGUI操作ができなくなるのですが、await・asyncを用いて呼び出した関数を処理している間はGUI操作が可能になります。
GUI操作と並行で処理ができる、という意味で、await・asyncは非同期処理であると言えます。

以下、Windows Formのサンプルコードです。
3秒後にボタン押下時のシステム時刻をラベルに表示するというサンプルコードであり、await・asyncを用いたボタンとそうではないボタンを用意して挙動の違いを確認します。

【サンプルコード】

・From1.cs(デザイン)

・Form1.cs(ビジネスロジック)

【実行結果】

・Asyncボタンを押してから1秒以内にNoAsyncボタンを押下

→Asyncボタンの処理中もNoAsyncボタンを押下可能であるため、2つのボタンに対応するラベルの表示上、時刻の差異は1秒以内です。

・NoAsyncボタンを押してから1秒以内にAsyncボタンを押下

→NoAsyncボタンの処理中はAsyncボタンを押下不可能であるため、2つのボタンに対応するラベルの表示上、時刻の差異は3秒以上となります。


いかがでしたでしょうか。

説明を読んでも関数の挙動や目的がわからなかったのですが、自分で簡単なプログラムを作って動かしてみて理解できました。
今回の記事はC#でGUIのプログラムを作っている人以外には参考にならない記事だったかもしれませんが、簡単なプログラムを作って理解を深める例を示すことはできたのではないかと思っています。

C#:セマフォを用いた排他制御

排他制御の仕組みとして先日Mutexを取り上げました
今回は、同じく排他制御で使われるセマフォについて取り上げます。

セマフォがMutexと異なる点は、複数のプロセス・スレッドが資源を取得することができることです。
セマフォのコンストラクタで初期で解放する資源数や、解放できる資源の最大数を指定します。
WaitOne関数で資源取得待ちを行い、Release関数で資源解放を行います。Release関数の引数で資源解放数を指定することもできます。
(ただし、最大数を超える資源を開放するとSemaphoreFullExceptionとなるので注意が必要です)

セマフォは、同時に動くスレッド数を制限したいような重い処理がある時によく使われます。

以下は、セマフォを用いて同時に動くスレッド数を制限するサンプルです。

【サンプルコード】

・Controller.cs

・Processor.cs

【実行用バッチ】

・test.bat

【実行結果】

・test.bat

・Controller.exe

・Processor.exe


いかがでしたでしょうか?

排他制御の仕組みとしてMutexを説明したので、ついでに代表的な方法の一つであるセマフォについても説明しました。
Mutexよりも使用頻度は少ないと思いますが、同時に動くスレッド数を制限するための書き方があるというのは覚えておいて損はないと思います。

C#:共有メモリで可変長データを繰り返し送受信する

共有メモリは、同一メモリ上で実行されるプロセス間でデータをやりとりする場合に使用する仕組みです。
通常、プロセスで確保しているメモリは他のプロセスから参照することができないのですが、プロセス間で予め共有メモリとして使用するメモリのアドレスを共有することで、そのメモリは他のプロセスから参照可能となります。
ファイル等を介したやりとりよりも高速なため、高速化が求められる時に使用することが多いです。

目的の一つが高速化のため、データが作成され次第次々と共有する、という使い方になることが多いと思います。
今回は、そのような使い方を想定して、可変長データを繰り返し送受信するサンプルプログラムを作成しました。
書き込んだデータのサイズを伝えること、共有メモリの読み取り位置をずらしていくことがポイントとなります。

なお、今回は省略していますが、本来であれば書き込み中の読み取りを防ぐため、Mutex等の排他制御の仕組みを併用するべきです。
(参考までに、Mutexについては前回の記事で取り上げています)

【サンプルコード】

・Sender.cs

・Receiver.cs

【実行バッチ】

・test.bat

【実行結果】

・Receiverのコンソール


いかがでしたでしょうか。

今回は、共有メモリを用いたデータの受け渡しを紹介してみました。
記事ではjavaに書き方が近く理解しやすいC#で書きましたが、本当に性能が求められる場合はCやC++で書く場合が多いです。
しかし、その場合もロジックは同じなので、参考になるのではないかと思います。

C#:Mutexでの排他制御

排他制御の方法の一つとして、C#にはMutexと呼ばれる機能が用意されています。
何れか一つのスレッドがMutexによるロックを取得することができます。
他のスレッドによりロックが取得されている場合の処理を別途記述すれば、この機能を使用して排他制御が可能となります。

以下、サンプルコードです。

【サンプルコード】

【実行結果】


また、Mutexには、名前を付けることができます。
名前を付けることで、プロセス間でも排他制御が可能となります。
ただし、意図せずMutex名が被ると意図しないロックがかかってしまうため、扱いには注意が必要です。

【サンプルコード】

【実行結果】

※exeファイルを3回起動した結果。
 1つ目のプロセス…掴んで解放
 2つ目のプロセス…解放を待って掴んで解放
 3つ目のプロセス…解放を待って掴めず諦める


いかがでしたでしょうか?

C#には排他制御のための機能が色々と用意されています。
その内の一つが今回紹介したMutexであり、名前を付けることでプロセス間の排他制御も可能になります。
名前付きMutexは、プロセスをまたいだスレッドの制御だけでなく、同じ画面が複数立ち上がらないようにする、といった使われ方もします。
仕組みが単純なので使用しやすく、排他制御の機能の中では使用頻度は高いと思います。

排他制御の機能は他にも色々と用意されているので、今後も紹介していきたいと思います!