Linqによるソート:OrderByとThenBy

先日、あるクラスのソートのためにICompareble<T>を実装したラッパークラスを作成したのですが、
コードレビューの際にLinqのOrderByを使用すれば良いとの指摘を受けました。

以下のようなクラスとそのリスト、値の演算メソッドがあった際に、

class Hoge {
	public int No { get; set; }
	public int Value { get; set; }
}
var hogeList = new List<Hoge>(){ /* 要素たくさん */ };
int CalcHeavyForSort(int value) {
	var ret = 0;
	// 重い演算
	return ret;
}

次のように書くことで、

hogeList = hogeList.OrderBy(x => CalcHeavy(x.Value)).ThenBy(x => x.No).ToList();

1. Valueの演算結果により昇順でソート
2. 1によるソートの順序内でNoにより昇順でソート
を実行してソートされたリストを取得できます。

降順ならOrderByDescending, ThenByByDescendingです。
特殊な比較を行いたい場合は、IComparerを引数に与えることもできるようです。

引数で与えたラムダ式の実行も1要素1回だけのようですので安心ですね。
(内部でラムダ式の戻り値のリストを作成し、
インデックス同士を比較するメソッド内でその戻り値リストへアクセスしているようです。)

雑ですが、もしも次のようにソート時に同じ重い演算を複数回実行する必要がある場合は、

hogeList = hogeList.GroupBy(x => CalcHeavy(x.Value))
		.ThenBy(x => CalcHeavy(x.Value) * x.No).ToList();

次のように匿名クラスでラッパーを作り、それをソートすると良さそうに思います。

hogeList = hogeList.Select(x => new {
		Source = x,
		CalcedValue = CalcHeavy(x.Value),
	})
	.OrderBy(x => x.CalcedValue)
	.ThenBy(x => x.CalcedValue % x.Source.No)
	.ToList(x => x.Source);

Linqは便利で可読性が高く保守もしやすいので、
シビアなパフォーマンスが求められるケースでなければ積極的に使っていきたいです。

USBドライバインストール時エラーの対処

先日、USBカメラを接続するためにドライバのインストールを行ったのですが、
その際に以下のエラーが発生し、インストールに失敗しました。
「このハードウェアのデバイスドライバーを読み込むことができません。
 ドライバーが壊れているか、ドライバーがない可能性があります。(コード39)」

結論から言うとWindowsセキュリティ設定が原因で、

Windowsセキュリティ->デバイスセキュリティ->コア分離->メモリ整合性をオフに変更

により解決しました。
以下、解決までの過程です。

1. 試行錯誤
次のようなことを試したのですが、解決も原因特定もできませんでした。
・カメラやケーブル、接続ポートを変更
・メーカーHPにてドライバの対応OS, CPUの確認
・ドライバを最新のものに更新

2. PC初期化
社内の他のいくつかのPCでは問題なく成功しており、
PC自体に原因がありそうだったのでPCの初期化も行いましたが、
それでもインストールは成功しませんでした。

3. メーカー問い合わせ・解決
にっちもさっちも行かなくなり、メーカーさんに問い合わせたところ、
次の手順でWindowsのセキュリティの設定を緩めれば良いと教えていただき、
無事解決しました。
スタート->設定->更新とセキュリティ
 ->Windowsセキュリティ->デバイスセキュリティ
  ->コア分離->コア分離の詳細
   ->メモリ整合性をオフに変更

原因となったメモリ整合性、PCによっては出荷段階で既にオンになっているようなので、
ドライバのインストールに失敗した際には確認してみると良いかもしれません。

その後、本件について補足情報などないか検索していたところ、
エラーメッセージ+エラーコードがタイトルの記事に解決策が掲載されているのを発見しました。
プログラミングの際はエラー発生の初期段階でエラーメッセージの検索をするのですが、
今回は失念していました。今後は気を付けたいです。

Reflectionによるプロパティ名の取得

先日、クラスの持つプロパティ名をExcelファイルに列挙すると言った作業を行うことになりました。
対象となる複数のクラスから特定の条件を満たすプロパティの名前のみを列挙する必要があり、
始めは手作業で地道にコピーしていたのですが、途中でReflectionを用いれば自動で列挙可能だと気付きました。
プロパティには列挙条件を示す属性が付与されていたのですが、
属性を取得できることを失念していました。

取得には以下のようなコードを使用しました。
※正確に再現したコードではないのでミスなどあるかもしれません


private static List<string> GetHogeIsHugaPropertyNames(Type type) {
    return type.GetProperties()
               .Select(p => (p, Attribute.GetCustomAttribute(p, typeof(HogeAttribute)) as HogeAttribute))
               .Where(x => x.Item2 != null && x.Item2.IsHuga)
               .Select(x => x.p.Name)
               .ToList();
}

これに気付かなかったため時間を少し溶かしてしまいました。
何か作業する際は開始前に作業手順を確認し、
繰り返し手作業を行う必要があるようならどうにか自動化できないかを考えるようにしたいと思います。

ディスプレイサイズとコードの読みやすさ

2週間ほど前に業務で使用するディスプレイを新調していただけました。
23.5インチほど(解像度1920*1200)から31.5インチ(解像度2560*1440)になったのですが、
コーディングがやりやすくなって大変ありがたいです。
コードの表示領域が大きくなるとこれだけ変わるのかと驚いています。

特にコードの読みやすさが格段に上がりました。
今までは横に長いコードに読み辛さを感じていたのですが、
視野内中心部に余白有りでコードが表示できるようになり問題がなくなりました。

適宜改行を挿入して読みやすく整形しておくに越したことはないと思いますが、
開発者全員が大きなモニタを使用することが確かなプロジェクトであれば、
多少横に長いコードを書いても支障はないのかもしれませんね。

ReSharperのInlay Hints機能の表示切り替え

3カ月ほど前からVisualStudioに拡張機能のReSharperを導入しました。
リファクタの提案をしてくれたり、スニペットを登録できたりと、何かと便利に感じています。

そのReSharperなのですが、デフォルトで型推論varの実際の型であったり、
引数のパラメータ名であったりを表示してくれる機能 Inlay Hints があります。
この機能、他者が書いたコードを読む際には大変便利なのですが、
下記例のように1行が長くなってしまい、逆に不便に感じることがしばしばあります。

a
Inlay Hintsで冗長になる例

そこで、任意のタイミングでInlay Hintsの表示/非表示を切り替える方法があれば良いのにと思い調べてみたところ、
ReSharperの公式マニュアル[1]に記載されていました。
以下の方法でできるようです。

1. スクロールバー上部アイコンを右クリックして表示したコンテキストメニューから切り替える
2. エディタ上で Ctrl+Shift+Alt+5 ショートカットキーを押す
3. ResharperのOptions -> Environment -> Inlay Hintsで、
Enableのチェックを外す or visibilityをShowAlwaysから別の項目に変更する


1. InlayHintsコンテキストメニュー


3.-ReSharperのOptions

2は押すキー数が多く、3はOptionsウィンドウを開くのに一手間かかるので、
この中だと個人的には 1のコンテキストメニューが一番手軽だと感じました。

マニュアルには、visibilityをPush-To-Hintにすることで、
Ctrlキー長押し?やCtrlキー2回押しで表示を切り替えれる旨の記載があるのですが、
こちらは上手く再現ができませんでした。
圧倒的にこちらの方が手軽なので、VisualStudioにて再現できた方がいれば、
その手順など教えていただけると嬉しいです。

[1] インレイヒント | ReSharper: https://pleiades.io/help/resharper/Inline_Parameter_Name_Hints.html

プログラミング言語の名称の由来 Part 2

大変遅くなりましたが、言語の由来Part2です。

・Java
断定はされていないようなのですが、
言語ロゴがコーヒーカップであるようにコーヒーが由来のようです。
ジャワコーヒー(Java Cofee)のJavaではないかということのようですね。

・Python
イギリスのコメディ番組「空飛ぶモンティ・パイソン」から取られたようです。
わかりやすく特徴的なだけにこの由来は有名かもしれませんね。
開発者は短くて個性的で少し不思議な名前を付けたいと思っていたようなので、
印象に残りやすいのも納得です。

・Rust
植物に寄生するさび菌に由来するようで、堅牢(Robust)の部分文字列でもあるそうです。
開発者チームに自転車好きが多かったためロゴは歯車になった、とどこかで見かけていたため、
てっきり金属の錆のことだと思っていました。

・Dart
最近名前を見聞きする、クロスプラットフォームフレームワークのFlatterで使用される
Dartの名称の由来はググり力が足りず調べても見つかりませんでした。
どなたか知っておられる方がおりましたら教えていただけますと幸いです。

他にもいくつか調べたのですが、書くのにあまり時間をかけ過ぎてもアレなのでこの辺で。
こうやって言語の由来を調べてみると、開発者のことが垣間見える感じがして良いですね。
皆さんも息抜きに自身の好きな言語の由来を調べてみるのはいかがでしょうか。

[1] Java – Wikipedia: https://ja.wikipedia.org/wiki/Java
[2] General Python FAQ — Python 3.10.0 documentation:
https://docs.python.org/3/faq/general.html#why-is-it-called-python
[3] Internet archaeology: the definitive, end-all source for why Rust is named “Rust”:
https://www.reddit.com/r/rust/comments/27jvdt/internet_archaeology_the_definitive_endall_source/

プログラミング言語の名称の由来 Part 1

今まであまり考えたことがなかったのですが、
ふとC言語の”C”とは何ぞやと思い、
C言語及び関連言語の名称の由来を調べてみることにしました。

・C言語
B言語の改良した言語、でC言語だそうです。
流石にA, B, C…のCではないだろう、と思ったら似たようなもので驚きました。
そのC言語の由来となったB言語自体の由来は、
BCPL(Basic Combined Programming Language)を元に開発されたため
その短縮形である、という説が一般的なようです。
こちらはA言語が由来ではないのですね。
(BCPLやその元のCPLも同様にA言語由来ではないようです。)
因みにA言語の由来はa programming languageの略だそうです。。。

・C++
Cを一歩進めたものということで、CをインクリメントしてC++, 納得です。

・C#
インフォテックでもメインで使用しているC#ですがその由来は、
C++を更にインクリメント(改善)して C++++

4つ並んだ+が#に見えるので C#
だそうです。
#そのものの意味を含んでいないとは思わず、調べた中で一番驚きました。

その他の言語の由来もいくつか調べてみたのですが、
長くなりそうなので、また別記事に分けて紹介しようと思います。

参考:
[1] C言語(C language)とは – IT用語辞典 e-Words(https://e-words.jp/w/C%E8%A8%80%E8%AA%9E.html
[2] B言語(https://ja.wikipedia.org/wiki/B%E8%A8%80%E8%AA%9E
[3] A言語(https://ja.wikipedia.org/wiki/APL
[4] C++言語とは – IT用語辞典 e-Words
https://e-words.jp/w/C-_-_%E8%A8%80%E8%AA%9E.html
[5] C#(C Sharp)とは – IT用語辞典 e-Words(https://e-words.jp/w/C-.html

Visiual Studioの右クリック時メニューに項目を追加する方法

先日、Visual Studioでコードエディタ上を右クリックした際のメニュー*に、
上部メニュー内の項目(ビルドなど)があると良いな~と思うことがありました。
* コンテキストメニューと言うそうですね

少し調べてみたら方法がわかったので、備忘録も兼ねて以下に記載します。

1. 上部メニューのツールからカスタマイズを開く

2. カスタマイズのコマンドタブで
2-1. コンテキストメニュー:エディタコンテキストメニュー|コードウィンドウを選択

2-2. コマンドの追加を開き、目的のコマンドを追加

以上の手順により、コードエディタ上で右クリックした際のメニューに目的の項目(コマンド)を追加できました。

頻繁に使うわけではないけれども上部メニューから一々実行するのは手間な場合に、
ショートカットキーと違って覚えておく必要のない、
今回のコンテキストメニューへの追加が便利なのかな、と思います。

参考にさせていただいたのは以下のサイトになります。
ありがとうございました。
Sunday Programmer’s Report: Visual Studio のコンテキストメニューに「Blend で開く」を追加する

Strategyパターン

たまの休日に一部の復習も兼ねて、”Java言語で学ぶデザインパターン入門”を亀のようなペースで読み進めています。
個人的に一番好きなパターンはStrategyパターンです。
このパターンは、インタフェースを定義してアルゴリズムを交換可能にするもので、
典型的な使いどころには、ゲームにおけるプレイヤーAI(CPUなどとも呼ばれますね)の思考ルーチンが挙げられます。
例えば、囲碁や将棋などの対戦ゲームにおいて、戦略の異なるAIをこのパターンで実装します。
以下のような形ですね。


public interface IPlayerStrategy {
    // 入力されたゲーム状態を元に行動を決定
    PlayerAction DetermineAction(GameState state);
}

public class AggressiveStrategy : IPlayerStrategy {
    public PlayerAction DetermineAction(GameState state){
        // 攻撃的な戦略に基づいて行動決定
    }
}

public class DefensiveStrategy : IPlayerStrategy {
    public PlayerAction DetermineAction(GameState state){
        // 防御的な戦略に基づいて行動決定
    }
}

public Player {
    private readonly IPlayerStrategy _strategy;

    public Player(IPlayerStrategy strategy){
        _strategy = strategy;
    }

    public PlayerAction GetNextAction(GameState state){
        return _strategy.DetermineAction(state)
    }
}

名が体を表す良いパターンだと思います。
個人の趣味ですが、典型例がゲームなのも良いですね。

実務経験はほぼないので、憶測になってしまうのですが、
実務であれば例えば、あるクラスにおいて、インスタンス生成時に決定される同一のフラグによって挙動を切り替える処理が何度も登場するような場合に、
Strategyパターンを適用できるのではないかと思っています。
インタフェースを切り、フラグのオンオフの挙動をそれぞれその具象クラスに切り出すことで、
外部のクラスには影響を及ぼさずに、フラグ毎の処理の見通しを良くできるような気がしています。

経験を積んで、パターンの使いどころを見極められるようになりたいです。

using declaration

先月研修でC#の勉強をしていたのですが、C#8.0からusingステートメントが、
以下のようにローカル変数宣言の先頭に追加する形で行えるようになっていたことを知りました。
(using declarationと呼ぶそうです)

// after 8.0
using var sw = new StreamWriter("hoge.txt");

// before 8.0
using (var sw = new StreamWriter("hoge.txt"))
{
}

8.0以前はその後の処理を記述する際に中括弧やインデントが必要だったのですが、
この形式だとネストを減らすことができてありがたいです。

ただ、Disposeの呼び出しがスコープの末尾なため、
記述の長いメソッドで利用するとリソースの解放が遅くなり、
場合によっては支障が出るのではないかと思ったのですが、
そもそもメソッドの長さが適切であれば問題ないことに気付きました。

メソッドの長さは適切に、ネストは浅く、シンプルなコードを書くよう心掛けたいです。