C#のタプルと分解

C#7で追加されたタプルのフィールドを分解する構文について、タプル専用の機能ではなくユーザ定義の型でも分解が行えると知ったので試してみました。

タプルのフィールドを分解する構文は以下のようになります。


var t = (Value1: 2, Value2: 3D);
var(v1, v2) = t;

1行目で2つのフィールドを保持するタプル変数tを作成し、
2行目で変数tのフィールドをv1とv2に分解しています。

これだけでは意味が無いですが、メソッドの戻り値はタプルで返し、
メソッド実行側はすぐに分解して使用したい場合などに役立ちます。

上記の分解と同様のことを行うには、クラスや構造体にDeconstructメソッドを実装します。拡張メソッドでもOKです。
KeyValuePair構造体のDeconstruct拡張メソッド実装例は以下のようになります。


public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> pair, out TKey key, out TValue value) {
    key = pair.Key;
    value = pair.Value;
}

例えば、Dictionaryの各要素をforeachで処理する場合、今まであれば以下のようになります。


var dic = new Dictionary<string, int>();
foreach (var pair in dic) {
    Console.WriteLine(pair.Key + "=" + pair.Value);
}

Deconstruct拡張メソッドを実装して分解が行えるようになると、以下のような実装が可能になります。


var dic = new Dictionary<string, int>();
foreach (var (name, score) in dic) {
    Console.WriteLine(name + "=" + score);
}

変数pairを使用する必要がなくなり、pair.Keyとpair.Valueではなく、本来のフィールドの意味を表す変数名を名付けて利用できるようになりました。

 

Visual Studio 2017 がフリーズ

先週くらいからVisual Studio 2017 が良くフリーズして再起動するようになり困っていました。

最近の環境変更で考えられるのは、Version15.4.3になったことと、Xamarin関係をインストールしたこと。

Visual Studio自体や拡張機能の更新も全て行っており、問題はないはず。

なんとなくReSharperが怪しいのではと思い、JetBreinsのサイトを見てみると、現在使用しているのよりも新しいReShaperがある。拡張機能の更新プログラムに何故表示されないのかは分からないが、ダウンロードしてインストールしてみると、フリーズがなくなったみたい。とりあえずは解決です。

ログビューワソフト

社内用にログビューワソフトを作成しました。

弊社が作成するPCソフトは必ずログファイル出力を行えるようにし、何らかの問題が発生した時にお客様の工場などに行かなくてもログファイルを調査することで大概のことは解決できるようにしています。

ログファイルは単なるテキストファイルなので、今まではテキストエディタを使用して調査を行っていましたが、専用のビューワソフトを作成したほうが効率が良いのではなかろうかと考え、社内用に作成してみました。

今ある機能は、ログ内容に応じた色分け表示、正規表現検索、検索結果の一覧表示、複数ファイルの一括表示、選択行からの相対時間表示など。

今はまだ機能が多くないのですが、これから必要に応じて機能追加をしていくつもりです。

UWP対応

先日、ラズペリーパイ3 + Windows 10 IoT Core の案件があり、せっかくなのでいつも使用している社内ライブラリのUWP(ユニバーサル Windows プラットフォーム)版を作成しました。

共通化できそうなソースコードは共有プロジェクトに移動した結果、UI関係やWindows依存な箇所以外はほぼ共通化が出来ました。単体テストも共通化出来ましたので動作確認もスムーズでした。

これで今後のUWP案件で効率良く開発できる準備が整いました。

マークダウンメッセージボックス

メッセージボックスをマークダウン記法で記載できると、表示方法の幅が広がり役立つのでは無いかと思い、社内ライブラリに追加してみました。
スタイルシートも設定できるようにしました。

使い方は以下のようになります。


var msg = new MarkdownMsgBox("#ヘッダA\n* 項目A\n* 項目B\n\n##ヘッダB\nメッセージA\nメッセージB\n\n-----\n1. 項目C\n1. 項目D", "テスト", MsgBoxButtons.OKCancel);
msg.StyleSheet = "h1 {font-size=30pt;  border-bottom: solid 4px Gray; color: Blue;}\nh2 { font-size = 20pt; border-bottom: solid 2px Gray;color: DarkBlue; }";
msg.Show();

結果のメッセージボックス表示は以下のようになります。

KeyValue属性

C#のお話です。

KeyとValueのペアを定義できる属性があると汎用に使えて便利ではなかろうかと思い、KeyValueAttribute属性クラスと、列挙型の場合に簡単にKeyValue属性の値にアクセスするためのEnumInfoクラスを作成してみました。以下に使用例を記載します。


//KeyValue属性を使用した列挙型の定義
public enum Idol {
    [KeyValue("Age", 16), KeyValue("Height", 162), KeyValue("BloodType", "A")]
    Chihaya,
    [KeyValue("Age", 14), KeyValue("Height", 145), KeyValue("BloodType", "O")]
    Yayoi,
    [KeyValue("Age", 13), KeyValue("Height", 158), KeyValue("BloodType", "B")]
    Ami,
    [KeyValue("Age", 13), KeyValue("Height", 158), KeyValue("BloodType", "B")]
    Mami,
}

//列挙型の拡張メソッドクラス
public static class IdolExtension {
    private static EnumInfo<Idol> EnumInfo { get; } = new EnumInfo<Idol>();
    public static int Age(this Idol idol) => EnumInfo[idol].GetValue<int>("Age");
    public static int Height(this Idol idol) => EnumInfo[idol].GetValue<int>("Height");
    public static string BloodType(this Idol idol) => EnumInfo[idol].GetValue<string>("BloodType");
}

//拡張メソッドの使用例
public void Sample() {
    int age = Idol.Chihaya.Age();
    int height = Idol.Chihaya.Height();
    string bloodType = Idol.Chihaya.BloodType();
}

上記のように、簡単に列挙型の拡張メソッド(Age,Height,BloodType)が出来上がりました。
静的なデータの場合はこの方法で拡張メソッドが定義できます。

しかし、動的なデータの場合は、今まで通り拡張メソッドを自力でゴリゴリ書かないといけないですね。属性でラムダ式が使えれば改善できると思うのですが。残念です。

波形発生器クラス

制御系ソフトでは外部からのAD入力値をロギングして演算や制御を行うことがよくあります。

社内での開発時はAD入力機器が無い場合が多いので、AD入力のデバッグ用に波形発生器クラスを社内ライブラリに実装しています。

このクラスを使用すると、指定した条件の経時変化波形を作成できます。今のところDC ・矩形波・サイン波・CSVファイルによる任意波形の4種類に対応しています。

あとは必要になったらパルス波・三角波・ノコギリ波・複数の波形発生器の合成波くらいを実装すればだいたいのことは試せるはず。