C#非同期Methodは#defineで

昨年からの案件で追われまくり、なかなか記述できないことが多く誰のためにもならない気配ですが、気を取り直してぼちぼち再開です。 巷で流行りの非同期メソッドについて思うがままに私事のTipを残しておきます。自分のためにも。 今更ながら.Net4.0と.Net4.5で大きな違いを述べるのもお恥ずかしい限りでありますが非同期メッソッドのの構文が大きく変化したことです。  非同期の歴史を語ったりしませんが、async await を付ける付けない。運用環境の.Netバージョンによって手前味噌のライブラリーが思わぬ副作用が出ることを経験し、今更ながらプリプロセッサのありがたみが身に沁みます。往年の開発者たちはC++の時代にライブラリーの使い分けや環境の違いを吸収するためにプリプロセッサをフルに活用していたあの時代のテクニックです。  特になにか新しいことをするのではなく、しっかり#define でシンボルを定義若しくは定義解除(#undef)して.Net4.0と.Net4.5のコンパイルを正確に記述するだけです。基本的にはProjectの条件付きシンボルをコンパイル前に定義する。

#if DotNet20
        //APM IAsync Callback
        public void CallBackRead()
        {
            _ReadCallbake = new AsyncCallback(OnRead);
            _shIo.BeginRead(_Buff, 0, BuffSIZE, _ReadCallbake, null);
        }
#endif
#if DotNet40
        public Task<string> AsyncRead()
        {
            var tcs = new TaskCompletionSource<string>();
            byte[] bff = new byte[ BuffSIZE];

            var rLength = Task<int>.Factory.FromAsync(_shIo.BeginRead, _shIo.EndRead,
                bff,0, BuffSIZE,null);
            
            var str =  Encoding.ASCII.GetString(bff, 0, rLength.Result);
            tcs.SetResult(str);
            return tcs.Task;
        }
#endif
#if DotNet45
        public async Task<string> AsyncRead()
        {
            byte[] bff = new byte[ BuffSIZE];
            int length = await _shIo.ReadAsync(bff, 0,  BuffSIZE);

            var str = Encoding.ASCII.GetString(bff, 0, length);
#if DEBUG
            Console.WriteLine("Debug: "+str);
#endif
            return str;

        }
#endif

 

ジェネリック・ラムダ・3項演算子・合体演算子

 面白いサンプル作れなかったが、やっと思いつきました。NullObjectならぬNullMethod?

    //ジェネリックメッソッドでnullチェック
        Action NullFunc<T>(T o)
        {
      //3項演算子でoがnullなら何もしないデリゲートを返す。null以外ならあえてnullを返す。
            return o == null ?  (Action)( () => { } ): null;
        }
    //メインのStream系処理が終了したのでリソース解放 忌まわしいnullチェックを簡略化
        public void close()
        {
      //Actionがnullだった場合_ShIO及び_Shellにはインスタンスが有ることを保証されているのでリソース解放(_XXX.Close)
            (NullFunc<Stream>(_ShIO) ?? _ShIO.Close)();
            (NullFunc<SshShell>(_Shell) ?? _Shell.Close)();
        }

 若しくは

        public void close()
        {
            
            Func<bool,Action> NullFunc =  o =>   o  ? (Action)( () => { } ): null;
      
            (NullFunc(Null == _ShIO)  ??  _ShIO.Close)();
            (NullFunc(Null == _Shell) ?? _Shell.Close)();
        }

メッソッドチェーンも入っているけど、まぁいいか。とにかく括弧が多すぎて可読性は落ちるのが問題  (2番目が説明楽だな。)

VisualStudio アウトライン

このブログの書き始めも、VSのショートカットの記録から始まっているように普段意識しないがそれを忘れると大変能率が落ちしまうで記録しようと心掛けている。空気や水のありがたさと同じ。

その中でコードを書くときにコメント以上に役に立つのが「アウトライン」(ブロックを+折畳んだり-展開したりする。あれ)。

  1. 通常よく使うのがCtrl+M,Ctrl+L(折畳/展開)でnamespaceごと折畳そしてCtrl+M,Ctrl+O(定義折畳)
  2. 次によく使うのがCtrl+M,Ctrl+Mで現在のカーソルのメッソッドブロック又は#region~#endregionの折畳/展開(このショートっカット群はほとんどトルグになっています。)
  3. 全体を展開する場合はCtrl+M,Ctr + Pで全展開(全てのアウトライン情報を取り消します。)
  4. Ctrl + M,Ctrl + Pの後はアウトライン情報が無い状態なので再度折畳むにはCtrl+M,Ctrl+Oで定義折畳
  5. 選択した範囲を折畳むにはブロック折畳はまず{ }ブロックを選択{/}にカーソルを移動後Ctrl + Shift + }しブロック内選択後Ctrl+M,Ctrl+Hでアウトライン情報新規作成、取り消すにはCtrl+M,Ctrl+U
  6. #region 説明文書~#endregion#region[Tab]で自動的に#endregionが記述されますので説明文書を記載後#endregionを移動させてCtrl+M,Ctr+Mで折畳
  7. 基本的に///で<summary>が自動的に記述されますがこれも折畳めますので折畳んだことを考えるとメッソッドの説明は///の後に記述しないで/// <summary> 言い訳とか記述すると折畳時の可読性が上がります。インテリセンスでは問題ないけどXMLドキュメント作成の際は注意が必要かも。

EntityFramework6.1 for DeskTop

MVCのお勉強もひと段落したのでFormアプリにEF6.1でもかましてみようかとコーヒー飲みながら休憩時間にアタック 結論から言うと本業に影響するほど嵌まりました。ASP.Net MVCからEFを利用する場合ほとんどオートメーション それをDeskTopアプリに適応するにはEF6.1を理解していないと何もできないことに気付かされた。

今回はSqlServerCompactでローカルファイルとする。 またテスト用データを準備する。

問題点1.Debug/ReleaseフォルダにローカルDB(.sdf)がフルパス指定 ConnectionStrings指定でData Source指定にDataDirectoryが使えない。

問題点2.EF61で非常に便利になったMigration機能が初期状態では使えない。

問題点1  開発アプリ起動時にAppDomainにDataDirectoryを追加設定  AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory);  これでSQLServerCompactの接続文字列は以下のように記述

<connectionStrings>
    <add name="UtilPassContext"
         connectionString="Data Source=|DataDirectory|\UtilPass.sdf"
         providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>

VS2012 Changed Thems.

 設計時に昔、偉い人から教えてくれたことでクラス属性の変数若しくはプロパティーをよく吟味しなさいと言われた。しかし経済学的にその属性はそのコミュニティー(Contex)が与えた一時的な状態(Status)であるらしい。当たり前のような、なんだか違うように思えたりしたりしてモヤット気持ち悪い(文章も><);。 まぁ属性はあくまで[has a]であるもちろん一時的な状態も含めて、そんなわけで無料のVS2012の外観の状態を一時的に変化させてみる。そろそろ衣替えの時期だし世の中はクリスマスだし

VS2012無料の衣替え

  1. 材料をDownload   Click To
  2. %ProgramFiles%\Microsoft Visual Studio 11.0\Common7\IDE\WDExpressExtensions\配下に「Themes」フォルダ作成
  3. 先ほどの材料(zip)を展開して2で作成した(Themes)フォルダにコピー
  4. 管理者権限で開いたCmd.exeから%ProgramFiles%\Microsoft Visual Studio 11.0\Common7\IDE\dexpress.exe /updateconfiguration実行
  5. 通常通りにVSExpress for desttop起動 ツール(T)→オプション(O)→環境 → 全般 → 配色テーマ(C) → 濃色
  6. あとは好みでテキストエディターの配色変更 ここ良い
注意事項
最悪再起不能なる可能性あり、事前に設定の保存  ツール(T)→インポート・エクスポート(I)を実施しておくこと南無。
南無
あくまで自己責任で(この世もあの世も、何事も自己責任)

Xamarin Studio Shortcut on OSX

 似非MACユーザとしXamarin Studioを使い始めてVisual Studioとの違いに脳内分裂気味ですが何事も人間なれが一番と言うことでShortcutから纏めていきます。出来るところから。

1行挿入(行末以外)
  • 空白行挿入(下行へ)
    Ctr+E , Enter
移動
  • 文字操作;一文字右へ移動 Ctr+F
  • 文字操作;一文字左へ移動 Ctr+B
  • 文字操作;一文字上へ移動 Ctr+P
  • 文字操作;一文字下へ移動 Ctr+N
  • 行操作:行の先頭へ移動 Ctr+A
  • 行操作:行の末尾へ移動 Ctr+E
  • 単語操作:一単語左へ移動 Alt+→
  • 単語操作:一単語右へ移動 Alt+←
  • 文頭 Cmd+↑
  • 文末 Cmd+↓
インデント
  • 深く Cmd+}
  • 浅く Cmd+{
コメント
  • トグル Cmd+/
縮小・展開

Opt+Shift+Cmd+←、 Opt+Shift+Cmd+→

削除
  • 一行削除 Cmd+X(選択しない状態)
  • 一条削除 Ctr+A,Ctr+K
  • 行操作、カーソル以降削除 Ctr+K
入替
  • 行操作:上行 Opt+↑
  • 行操作:下行 Opt+↓
  • 単語操作:左右入替 Ctr+T

残りはキーバンドを確認すること

定義
  • 移動 Cmd+D
  • 検索 Shift+Cmd+R
Window操作
  • 一画面 Opt+Cmd+1
  • 二画面(垂直分割) Opt+Cmd+2

なんだかEditor操作はVisulStrudioよりXamarinに軍配が、つぅーかOSXのショートカットそのままで便利

末尾再帰関数の最適化機能

 勘違いしていたので反省をこめて記述  本来ループ処理の出来ない関数型言語はデフォルトでコンパイラ等が対応、Python2.4は変態なので関数のAttrib(@tail_recursive)として実装済み,C#x64 Releaseのみコンパイラが最適化しれくれるそうです。  C#で末尾再帰関数はリファクタリング時に自力でループに変更した方が安全ですね。

 public int TailRecursive(int n, int res = 1)
        {
            if (1 == n)
                return res;
            var toatal = res * n;
            return TailRecursive(n - 1, toatal);
        }

変換後

public int LoopChangeTail(int n)
        {
            var res = 1;
            for (;;)
            {
                if (1 == n)
                    break;
                res *= n;
                n--;
            }
            return res;
        }

だけど、リファクタリング対象にするにはMethod命名ルールをどのようにするのか悩みどころです。