コレクションのループ処理で、要素とインデックスを使用したい場合の書き方

C#のお話です。

以下のようなコレクションitemsの各要素にたいして処理を行なう際に、処理内でインデックスが必要な場合はどのようなコードにするのが良いかについて。


var items = new[] { "a", "b", "c" };

 
レガシーな書き方だと以下です。
いまどきfor文でループしたくないですよね。


for(int index = 0; index < items.Length; index++) {
    var item = items[index];
    //indexとitemを使用する処理
}

 
foreachだと以下です。
forよりはマシですが、itemsからインデクサを使用して要素を取得するところが残念です。


foreach(var index in Enumerable.Range(0, items.Length)) {
    var item = items[index];
    //indexとitemを使用する処理
}

インフォテックの社内ライブラリを使用する場合、IListの拡張メソッドForEachが実装してあるので、以下のように実装できます。


items.ForEach((index, item) => {
    //indexとitemを使用する処理
});

上記の方法でだいたいは問題ないのですが、処理をラムダ式で実装出来なかったり、出来ても複雑になってしまう場合、インフォテックの社内ライブラリにIListの拡張メソッドAndIndexが実装してあるので、以下のように実装できます。


foreach (var (item, index) in items.AndIndex()) {
    //indexとitemを使用する処理
}

追加した拡張メソッドはとても単純な実装内容ですが、たったそれだけでコードが非常に分かりやすくなっていると思います。

WEBアプリ

今、弊社では珍しくWEBアプリを作成しています。

いつもはWindowsデスクトップアプリがほとんどですので、WEBアプリ作成に関するノウハウや社内ライブラリが少なく、悪戦苦闘中です。
ですが、新しいことを学習するのはとても楽しく、時間を忘れて没頭してしまいます。

フレームワークは、ASP.NET Core Blazorを使用したかったのですが、既存のDLLの兼ね合いで.net coreでは困難なため、.net frameworkが使用できるASP.NET Core MVCを使用しました。

WEBデザインを行っている兄に質問しまくって何とか形になってきました。

.NET Framework から .NET Core へ

C#などで作成した既存のプロジェクトを .NET Framework から .NET Core へ移植するのに必要な作業量を調べるツールが有ることを知ったのでメモ。

.NET Portability Analyzer

早速、社内ライブラリで試してみたところ、.NET Coreでさポートされていない機能の一覧が合計25箇所表示されました。DataContextとRemotingに関する内容が大半です。
これくらいなら対応できそうです。

あとは参照している別ライブラリ類ですが、どうも.NET Coreプロジェクトから.NET Framework を使用しているDLLが使用できるようなので大丈夫そうです。
試していないですが、以下のサイトなどで出来ているのでなんとかなるのでしょう。
https://qiita.com/soi/items/e1cf2abf9845164bf439

DataGridViewに任意のコントロールを表示

今回もまたWindowsFormsのDataGridViewコントロールを拡張したお話。

任意のコントロールを表示できるセルを実装しました。

セルのValueプロパティにコントロールをセットすると、セルの描画位置にそのコントロールが表示されます。

もちろん、セルに表示したコントロールを操作することが可能です。

今回の実装により、DataGridViewで表現できる幅がさらに広がりました。

DataGridViewのホットトラッキング

今回もWindowsFormsのDataGridViewコントロールを拡張したお話。

マウスカーソル下にあるセルの背景色・前景色を自動で変更する処理(ホットトラッキング)を社内ライブラリに実装しました。プロパティの設定だけで実現できるのでコーディング不要です。

内部処理は、DataGridViewのOnCellPaintingメソッドをオーバーライドし、マウスカーソル下かによってCellStyleを変更することで実現しています。

DataGridViewにグラフを描画

DataGridViewコントロールにグラフ表示を行う機能を追加しました。
現在対応しているグラフは、横棒グラフ・縦棒グラフ・積上横棒グラフ・線グラフ・面グラフ・点付き線グラフなど。

既存のグラフコントロールを使用して、セルのGraphicsオプジェクトに直接描画しているので、他のグラフに対応するのも簡単です。必要があれば円グラフや3Dグラフなども対応できます。

今回の実装により、DataGridViewで表現できる幅が広がりました。

画像処理ライブラリの機能追加

最近、画像処理案件が続いてあり、社内の画像処理ライブラリに色々と機能追加を行いました。

a) ライブラリの64bit対応
b) 画像処理の並列化
c) 欠陥素子補正
d) 色マッチング処理

まだまだ機能追加したいことがあるのですが、時間が足りないです。
無限に開発をしていたいのですが時間は有限なのでしかたないですね。

ログ + スクリーンキャプチャ

インフォテックで作成するソフトではログファイルを必ず出力するようにしています。

稼働している設備でなにか問題が発生した場合などにログファイルを調べれば、エラーメッセージ・例外スタックトレース・通信内容・シーケンス状態などが全てわかるようにしています。
これにより問題発生時の原因究明・問題改善が容易になります。

今回、ログ出力に機能追加を行い、エラーメッセージを表示する直前にスクリーンキャプチャ画像ファイルを保存する機能を追加しました。
これにより問題発生時の状況把握がさらに容易になります。

先日もこの機能のおかげで、装置問題発生時のA/D即値や波形が確認できたことで、問題が装置側にあることがすぐに分かり即解決できました。

64bitのOpenCV

画像処理ライブラリOpenCVを良く使用するのですが、いつも32bit版のDLLを使用しています。
本来なら64bit版を使用したいところですが、同じソフト内で使用する他のライブラリが32bitしか無いことが少なからずあり64bit版を避けていました。

今回、32bit版と64bit版でどの程度の性能差があるのかが気になり確認してみました。
その結果、64bit版に変更するだけで3割くらい速度アップしました。
処理内容にもよるでしょうか、単純に速くなるのはありがたいです。
それと64bitにすることで1プロセスが使用できるメモリ上限も増えるので、メモリ不足の心配も少なくなります。

今後はできるだけ64bit版を使用するようにし、32bitでしか動作しないライブラリなどは32bitの別プロセスで実行し、プロセス間通信でやりとりする作りが良いと考えています。面倒ですけど。