Quantcast
Browsing Latest Articles All 1943 Live
Mark channel Not-Safe-For-Work? (0 votes)
Are you the publisher? or about this channel.
No ratings yet.
Articles:

C系プログラマが始めるPython

Pythonを勉強することになったきっかけ

前々から話題になっており触りたいと思っていたまま、時が過ぎてました...
つい最近、Python触れる子が周りにいたり、企業の人にも他の言語にも触れてみたらとアドバイスをもらったりしたので勉強するモチベが高くなったって感じです。

余談

この画像はちょまどさんが描かれたものです。Pythonちゃん可愛いですよね!
pythonChan

この記事を読む前に

投稿主はC/C++JavaC#をすでに触っているため、そういったC系の言語と比較した視点で記事を書いていくので予めご了承ください。

お〇ぱいそんを触りたい

ド下ネタな見出しですみません。ただ言いたいだけです。
ここから具体的なPythonの基本文法についてまとめてます。参考記事の内容を自分なりに省略しているので詳細は参考記事をご覧ください。

セミコロンが要らない

タイトルの通り過ぎてこれ以上書くことがないですが、文末にセミコロン付けなくていいらしので1タイプ手間が減りますね!!
個人的には普段C系の言語を触っているので違和感しか感じませんが笑

型の指定が要らない

C/C++などでは変数を宣言する際に型を明示しなければなりません。

C++
intnum=100;

これがPythonだとこうなります。

Python
num=100

C++やC#でいうautoやvar(型推論)的なことをPythonはデフォルトでやってるみたいですね。(動的型付け)
ただ、明示した方が良いこともあるので一長一短ですね。
ちなみに関数の引数や戻り値っも同様に型指定がありません。

中括弧が要らない(ifやforに括弧が要らない)

ないないだらけですね笑

Python
num=77ifnum%2==0:print("偶数です")else:print("奇数です")

中括弧がない代わりに:(コロン)で条件と処理を分けてるみたいですね。インデントをすることで階層を判断するみたいです
またifやfor、whileなどの条件に括弧をつけないそうです。
これなら中括弧の位置で戦争することが無いので平和だぁ...

switch~case、do~whileが無い

タイトルの通りありません。do~whileについてはほぼ使わないんですけどね。
switchの代わりにif~elif~elseで代用するみたいです。else ifではなくてelifみたいなので注意。(なぜ省略したんだろ...)

リストに型の制約がない

Cでいう配列なのですが、配列と違いPythonのリストは型の制約がないので数値型や文字列が混在していても大丈夫なようです。

Pythonのforは拡張for(C#でいうforeach)

Python
arrayList=["cat",100,25.25,"Python"]#リスト内をぶん回します
forarrayinarrayList:print(array)#indexで指定してforを回したい場合
forindexinrange(0,10):print(index)

上のコードのコメントの通りです。rangeを使うことで0から9の配列を用意しています。
ちなみにコメントは// の代わりが # で /*~*/ の代わりが ''' ~ '''です。

演算子系

  • インクリメント・デクリメント演算子が存在しない(+=や-=では使える)
  • //(小数点以下を切り捨て、整数値を低い方に合わせる)や**(べき乗)がある
  • 論理演算の&& や || 、! が and、 or、 notという予約語として扱われる。

関数

Pythonの関数は関数オブジェクトとして扱われています。

Python
defAdd(x,y):returnx+y

前述したとおり型指定が要らないのでこういう風に描けます。手前にdefを付けたら関数です。物凄くシンプルで好き。
しかもこれの凄いところが型指定が無いのでこんなこともできます。

Python
print(Add(2,5))print(Add(1.6,4.8))print(Add("Hello","World"))

C++やC#でいうテンプレート関数として扱えます。(<>で型指定しないのが便利すぎる)
ただ関数のオーバーロードが出来ないそうです。似たようなことをしようと思ったらデフォルト引数を用いればできるみたい。

pass文

pass文っていう処理書かなくてエラー出ずに通るっていう文があります。

Python
defAddPosition():#TODO:後で実装
pass

こんな感じで後で実装したいときとかにpass文を使うそうです。なるほどーって感じです。

その他

  • import が Cでいう #include
  • 連想配列(dict)、タプルが標準で使える
  • const や readonly、finalなどの定数のキーワードが無い。(慣習で大文字の変数は定数と扱っているみたい)
  • public や private などのアクセス指定子がない。(慣習でprivateなものには _を 1つ付けるとかなんとか)
  • virtualやoverrideがない。(継承して同名のメソッドを定義すれば可能)
  • 多重継承が可能。(その代わりjavaでいうインターフェースがない)

まとめ

ぱーっと基本的な文法についてはこんなものかなと思います。C++やC#でもあるような機能は省いています。詳細は参考記事をご覧ください。
軽く勉強してみて感じたのは可読性の高いコードを書きやすいなと思いました。
今後はPythonを用いて自動化やAIについての勉強もできたらなと思います。

またPythonについてご意見やアドバイスがありましたら気軽にコメントくださると嬉しいです!

参考記事

C言語系プログラマのためのPython入門
https://qiita.com/shiracamus/items/fd35c685e9679323471f

C#エンジニアが初めてpythonを学習して感じた違い
https://qiita.com/CEML/items/29944cbeb8e38171a630

C#からPythonに乗りかえるための両者の比較
https://qiita.com/kent-u/items/e6b210d38ca39b4cd107

C#erがPythonを勉強したので、違いについて比較しながら述べてみる その1 構文
https://hiroronn.hatenablog.jp/entry/20170717/1500281854

Python入門
https://python.keicode.com/

ASP.NET Core MVC 3.1 入門 その3 「Controller」

はじめに

ASP.NET Core MVC 3.1 のコントローラーついて、自分が学んだことを備忘録として記載します。
このフレームワークに殆ど触れたことが無い方に少しでも参考になれば幸いです。
誤り等あれば、ご指摘頂けますと大変喜びます。

前回の記事

ASP.NET Core MVC 3.1 入門 その2 「MVCプロジェクトの基本構造」

今回の流れ

  • MVCパターンの説明
  • コントローラーの説明
  • コントローラーを作ってみる
  • アクションメソッドの説明
  • 動かしてみる
  • 振り返り

今回のゴール

  • MVCパターンにおけるコントローラーの役割を理解する
  • コントローラーを追加できる
  • アクションメソッドが何かを理解する

環境

IDE
Visual Studio 2019
言語
C#

MVCパターン

コントローラーの説明に入る前に、
まずはMVCパターンについて確認しておきましょう。
全体像を把握したうえで、コントローラーについて具体的にみていきます。

MVCパターンとは

画面表示と、ビジネスロジックの分離を実現するためのアーキテクチャ(設計手法)です。

要はHTMLの生成といった画面表示のための処理と
DBアクセスのようなデータの管理/操作をするための処理
これらを分離させるために先人が考え出したプログラムの作り方の一つです。

MVCというのは構成要素の略称で、以下の単語の先頭文字をそれぞれ取り出したものです。

Model – View – Controller

実現できると、それぞれが分離しているので変更・修正があった場合、お互いに影響を受けづらく、Testability (テスト容易性) が高まるというメリットがあります。

画面に表示する項目の書式変更によってDBアクセス処理に影響が出たり、
DBの軽微な定義変更によって画面表示処理に影響が出るといった事態が発生しづらくなります。

各要素の役割

要素概要
Modelデータの管理/操作といったビジネスロジックを担当
Viewデータ入力用のフォーム、処理結果の表示といったアプリケーションのフロントエンドを担当
ControllerModelとViewの橋渡しを担当

コントローラー

コントローラーとは

MVCの全体像を把握したうえで、 コントローラー(Controller)について具体的にみていきます。
MVCにおいて、 ModelViewの橋渡しを担当する要素です。

Viewから受け取った生データを Modelに引き渡し、
Modelでの処理結果を Viewに返す

というのが主なお仕事です。

よくある会員登録処理で、 コントローラーのお仕事を確認してみましょう。

  1. 会員登録フォームに入力された情報を Viewから受け取る
    Viewから生データを受け取る
  2. 実際の会員登録処理(DBアクセス)を担当する Modelに情報を引き渡す
    → 受け取ったデータを Modelに引き渡す
  3. 会員登録の処理結果(成功/既登録により失敗 etc)を受け取る
    Modelから処理結果を受け取る
  4. ユーザーに会員登録の処理結果を通知するために、 Viewへ処理結果を返してあげる
    → 受け取った処理結果を Viewに返す

コントローラーを追加する

では実際にコントローラーを作ってみましょう。

ASP.NET Core MVC 3.1 のプロジェクトを作成する

まずは「Web アプリケーション(モデル ビュー コントローラー)」テンプレートでプロジェクトを作成します。

image.png

ソリューションエクスプローラーを眺める

各フォルダ/ファイルの概要については前回の記事をご参照ください。
お作法として、 コントローラーは必ずControllersフォルダ配下に配置してください。

image.png

コントローラーの追加

既にテンプレートに含まれているHomeControllerが存在しますが、
新しいコントローラーを追加してみます。

Controllersフォルダを右クリック > 追加 > コントローラー

と進んでください。

image.png

スキャフォールディング

以下のようなウィンドウが立ち上がると思います。
「スキャフォールディング」というのは、要は雛形を自動生成する機能のことを示します。
今回はコントローラーの雛形を自動生成してもらうために、この機能を使います。

最初から全ての コントローラーの基底クラスとなるControllerクラスを継承してくれたり、読み取りや書き込み用のメソッドを用意してくれたりと、手間が省けるので、 コントローラーを追加する際には普通にクラスとして追加するのではなく、この手順でスキャフォールディング機能を利用することをおすすめします。

今回は「MVC コントローラー - 空」を選択します。
よりリッチな雛形(CRUDに相当するメソッドが用意されている)もありますが、まずはまっさらなコントローラーを使っていきましょう。

image.png

続いてファイル名ですが、HelloControllerとします。
ここで重要なのは末尾をControllerとすることです。
末尾がControllerでないと、そのままではコントローラーとして検出されません。
※末尾がControllerでない場合は、Controller属性を付与する必要があります。
クラス名からControllerを取り除いた部分がコントローラー名とみなされます。

image.png

コントローラークラス

以上でコントローラーは追加できたと思います。
では、追加されたコントローラーのコードを見ていきましょう。

HelloController

まず注目して頂きたいのは、Controllerクラスを継承している点です。
コントローラーは通常Microsoft.AspNetCore.Mvc.Controllerクラスを継承します。
※前身のASP.NET MVC では必須でした。

publicclassHelloController:Controller{publicIActionResultIndex(){returnView();}}

アクションメソッド

次にIndexというメソッドをみていきます。
今回は「MVC コントローラー - 空」を使用しましたが、このIndexメソッドは最初から定義されています。

このメソッドは「アクションメソッド」と呼ばれるものです。

publicIActionResultIndex(){returnView();}

アクションメソッドとは

クライアントからの1リクエスト(ex 登録ボタンの押下)に対して、具体的な処理内容を定義するメソッドです。
上記のIndexメソッドが正にアクションメソッドとなります。
Controllerクラスとは、関連性を持った複数のアクションメソッドによって構成されます。
逆に言えば、一つ以上のアクションメソッドを束ねたクラスがコントローラーとなります。

アクションメソッドの規約

メソッドをアクションメソッドとして定義するためには、以下に代表される規約を全て守る必要があります。

  • コントローラークラス内に定義する
  • public
  • staticでない
  • 戻り値がIActionResultオブジェクト(後述)

上記のIndexアクションメソッドは上記の規約を全て守っているので、アクションメソッドということになります。

アクションメソッドの戻り値

繰り返しになりますが、アクションメソッドとはクライアントからの1リクエスト(ex 登録ボタンの押下)に対して、具体的な処理内容を定義するメソッドです。

従って、様々な処理をおこなうことが予想されます。
当然、様々な処理の結果、結果も様々となります。

  • 文字列
  • ファイルのデータ
  • 別のページへの遷移(リダイレクト)
  • 要求されたページが存在しない という結果

上記のような様々な結果を表現するために 「IActionResult」を実装した様々なクラス(IActionResultオブジェクト)が用意されています。

このIActionResultインターフェースはアクションメソッド内での処理に代わり、実際のHTTPレスポンスを生成する機能を提供しています。
我々が、HTTPレスポンスを直接的に意識することなく、開発ができるのはこの仕組みのおかげというわけです。

代表的なIActionResultオブジェクトを以下で紹介します。

主なIActionResultオブジェクト

概要
ContentResultテキストデータを返す
JsonResultJSON 形式のデータを返す
ViewResultテンプレート(ビュー)に基づいてページを返す
FileContentResult指定されたバイト配列をファイルとして返す
RedirectResult指定のアドレスに移動(リダイレクト)する
RedirectToActionResult指定のアクションに移動(リダイレクト)する
NotFoundResultステータスコード 404(NotFound)エラー を返す
EmptyResultなにもしない

利用頻度の高いIActionResultオブジェクトについては、対応するファクトリメソッドがControllerクラスに用意されています。
対応するファクトリメソッドが存在しないものについては、自分でnewする必要があります。

代表的なものを以下に紹介します。

主なIActionResultオブジェクトのファクトリメソッド

ファクトリメソッドIActionResultオブジェクト備考
ContentContentResult
JsonJsonResult
ViewViewResultデフォルトでは「/Views/コントローラー名/アクション名.cshtml」を読み込む
FileFileContentResult
RedirectRedirectResultリダイレクト先をURLで指定する
RedirectToActionRedirectToActionResultリダイレクト先をアクション名(+コントローラー名)で指定する
NotFoundNotFoundResultステータスコードを返却する場合は、StatusCodeResultクラスを利用することもできる(対応するファクトリメソッドがないステータスコードも存在する)

動作確認

アクションメソッドを修正する

自動生成されたIndexアクションメソッドを以下のように修正します。
現時点では、Viewを追加していないので、Viewテンプレートを経由せずにテキストデータを返すContentResultを戻り値として返してみます。
Contentメソッドは、上述した通りContentResultのファクトリメソッドです。

publicclassHelloController:Controller{publicIActionResultIndex(){returnContent("Hello World!");//修正箇所}}

実行

修正したら、F5で実行してみましょう。
テンプレートで用意されているトップページが表示されると思います。

image.png

ここでアドレスバーから手入力でURLを変更します。
変更前は以下のようになっているかと思います。
XXXXXの部分はポート番号を示しています。
環境とタイミング次第で異なりますので、ご自身の画面に表示されているものから変更する必要はありません。

https://localhost:XXXXX/

以下のようにアドレスバーから手入力でURLを変更してください。
末尾にHello/Indexを追加します。

https://localhost:XXXXX/Hello/Index

変更後、Enterを押下すると、以下のように「Hello World!」表示されると思います。
以上で動作確認は終了です。

Hello/Indexとすると、なぜHelloControllerIndexアクションメソッドが呼び出せるのかについては、次回以降の記事にします。

image.png

アクションメソッドを振り返る

ここまでのおさらいも兼ねて、以下のメソッドを言葉にすると

Contentメソッドを呼び出し、テキストデータを返すための IActionResultオブジェクト(ContentResult)を生成し、戻り値として返す Indexアクションメソッド

ということになります。

publicclassHelloController:Controller{publicIActionResultIndex(){returnContent("Hello World!");}}

C++/CLIでConsole.WriteLine()は表示されるのにprintf()やcoutは表示されない時の対処法

概要

VisualStudio2015にて、C++/CLIプロジェクトとC#プロジェクトを同居させたソリューションを作っていました。C++/CLIの方でprintf()やcoutでログ出力しようとしたのですが、VisualStudioでデバッグ実行すると表示されませんでした(プログラムはそのまま動いていました)。
Console.WriteLine()での出力は表示されており、なんでかなーと思っていたら解決したので、書いておきます。ググってもあまりヒットしなかったので・・・

対処法

C#プロジェクトの、プロパティ⇒デバッグ⇒デバッガーを有効にするにある、「Visual Studio ホスティングプロセスを有効にする」チェックボックスのチェックを外すと表示されるようになりました。

その他

表示されていない時のことをもう少し詳しく書いておきます。

1つ目。表示されないと言いつつ、生成されたtest.exeを直接叩いた場合には、printf()やcoutで出力したログはコンソールに表示されていました。VisualStudioで動作させた場合には表示されていなかったという感じです。

2つ目。チェックボックスにチェックが入っている状態だと、実行時のコンソール上の表示が.exeではなく.EXEと大文字になっていました。

C# 入れ子のオブジェクトの内部構造を文字列に変換する方法 サンプルコード

このまま動作します。
コピぺ、編集して利用するためのコードの断片です。
自由に使って頂いて構いません。

例えば、以下の構造のオブジェクトを、以下のような文字列に変換できます。
オブジェクトの入れ子に対応しています。
デバッカが使えない環境で、オブジェクトの内容をログに出力して、デバック等に使用できます。

オブジェクトの構造.cs
usingSystem.Collections.Generic;classclass_1{publicList<string>a;publicintb=0;publicclass_1c;}
変換した文字列
▽(汎用.Form_Test+class_1)-------------------------------
|       ▽a(System.Collections.Generic.List`1[System.String])-------------------------------
|       |       ▽_items(System.String[])-------------------------------
|       |       |
|       |       △_items(System.String[])-------------------------------
|       |       
|       |       _size(System.Int32) = 3
|       |       _version(System.Int32) = 0
|       |       _syncRoot = Nothing
|       |       a[0](System.String) = "aaa"
|       |       a[1](System.String) = "bbb"
|       |       a[2](System.String) = "ccc"
|       |
|       △a(System.Collections.Generic.List`1[System.String])-------------------------------
|       
|       b(System.Int32) = 1
|       ▽c(汎用.Form_Test+class_1)-------------------------------
|       |       ▽a(System.Collections.Generic.List`1[System.String])-------------------------------
|       |       |       ▽_items(System.String[])-------------------------------
|       |       |       |
|       |       |       △_items(System.String[])-------------------------------
|       |       |       
|       |       |       _size(System.Int32) = 3
|       |       |       _version(System.Int32) = 0
|       |       |       _syncRoot = Nothing
|       |       |       a[0](System.String) = "ddd"
|       |       |       a[1](System.String) = "eee"
|       |       |       a[2](System.String) = "fff"
|       |       |
|       |       △a(System.Collections.Generic.List`1[System.String])-------------------------------
|       |       
|       |       b(System.Int32) = 2
|       |       c = Nothing
|       |
|       △c(汎用.Form_Test+class_1)-------------------------------
|       
|
△(汎用.Form_Test+class_1)-------------------------------

以下コードでオブジェクトを文字列に変換できます。

呼び出しかた.cs
s=ObjectToString(o);

以下の共通処理を任意の場所に貼り付ければそのまま使用できます。

共通処理.cs
usingSystem.Text;usingSystem.Reflection;/// <summary>/// 指定されたオブジェクトの内部構造の文字列表現を返却する。/// </summary>/// <param name="targetObject">内部構造の文字列表現を取得する対象のオブジェクト</param>/// <returns>オブジェクトの内部構造の文字列表現</returns>publicstringObjectToString(objecttargetObject){varbuf=newStringBuilder();_ObjectToString("",targetObject,buf,"");returnbuf.ToString();}/// <summary>/// 指定されたオブジェクトの内部構造の文字列表現を返却する。/// 内部呼び出し用なので、ObjectToString以外から直接呼び出さない。/// </summary>/// <param name="targetFieldName">解析するオブジェクトのフィールド名</param>/// <param name="targetObject">内部構造の文字列表現を取得する対象のオブジェクト</param>/// <param name="buf">オブジェクトの内部構造の文字列表現の出力先バッファ</param>/// <param name="nestString">オブジェクトの入れ子構造を表現するための文字列</param>privatevoid_ObjectToString(stringtargetFieldName,objecttargetObject,StringBuilderbuf,stringnestString){try{if(nestString.Length>=200){thrownewException("階層が深すぎるので解析を打ち切ります");}if(targetObject==null){buf.AppendLine(nestString+targetFieldName+" = Nothing");}elseif(targetObject.GetType()==typeof(byte)||targetObject.GetType()==typeof(short)||targetObject.GetType()==typeof(int)||targetObject.GetType()==typeof(long)||targetObject.GetType()==typeof(float)||targetObject.GetType()==typeof(double)||targetObject.GetType()==typeof(decimal)||targetObject.GetType()==typeof(char)||targetObject.GetType()==typeof(bool)||targetObject.GetType()==typeof(DateTime)){buf.AppendLine(nestString+targetFieldName+"("+targetObject.GetType().ToString()+") = "+targetObject.ToString());}elseif(targetObject.GetType()==typeof(string)){buf.AppendLine(nestString+targetFieldName+"("+targetObject.GetType().ToString()+") = \""+targetObject.ToString().Replace("\r\n","\r\n"+nestString+"    ")+"\"");}elseif(targetObject.GetType().ToString().IndexOf("System.Collections.Generic.List")==0){// 型:List(Of ...) への対応// リストの内部情報はType.GetFieldsから解析する事ができないので、自前で解析する。buf.AppendLine(nestString+"▽"+targetFieldName+"("+targetObject.GetType().ToString()+")-------------------------------");foreach(varfieldintargetObject.GetType().GetFields(BindingFlags.FlattenHierarchy|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance)){_ObjectToString(field.Name,field.GetValue(targetObject),buf,nestString+"|       ");}varcount=(int)targetObject.GetType().GetProperty("Count").GetValue(targetObject,null);for(varindex=0;index<=count-1;index++){varparam=newobject[]{index};varitem=targetObject.GetType().GetProperty("Item").GetValue(targetObject,param);_ObjectToString(targetFieldName+"["+index.ToString()+"]",item,buf,nestString+"|       ");}buf.AppendLine(nestString+"|");buf.AppendLine(nestString+"△"+targetFieldName+"("+targetObject.GetType().ToString()+")-------------------------------");buf.AppendLine(nestString);}else{buf.AppendLine(nestString+"▽"+targetFieldName+"("+targetObject.GetType().ToString()+")-------------------------------");foreach(varfieldintargetObject.GetType().GetFields(BindingFlags.FlattenHierarchy|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance)){_ObjectToString(field.Name,field.GetValue(targetObject),buf,nestString+"|       ");}buf.AppendLine(nestString+"|");buf.AppendLine(nestString+"△"+targetFieldName+"("+targetObject.GetType().ToString()+")-------------------------------");buf.AppendLine(nestString);}}catch(Exceptionex){buf.AppendLine(nestString+"▽"+"(解析中に例外発生)-------------------------------");buf.AppendLine(nestString+"|       "+ex.ToString());buf.AppendLine(nestString+"|       "+ex.Message);buf.AppendLine(nestString+"|       "+ex.StackTrace);buf.AppendLine(nestString+"|");buf.AppendLine(nestString+"△"+"(解析中に例外発生)-------------------------------");}}

今後習得したい技術

★目次
1.自己紹介
2.マスターしたい技術
3.現在の業務

【1】
C# WPFをメインで扱う会社。
本年6月より現職
以前は自社でも派遣でも作業するSE会社。
5年間で経験した言語は以下の通り;
C#: 2年5か月
Java:1年6か月
PHP:3か月
HTML・CSS:3か月
Excel VBA:1か月
ラダー :1か月(シーケンサ用の組込言語)
C、Mathematica、Matlab(大学時代に少しだけ)

【2】
1.NUnit
2.MVVM
3.Prism
4.Code First(Entity Framework)
5.非同期処理
6.リフレクション
7.追記
■1.NUnit:
単体テスト自動化フレームワーク。使えれば絶対武器になると思っている。
なお、現在の職場は、以前の現場では「結合テスト」と呼んでいたテストを「単体テスト」としている。
私が以前学習(JSTQBテスト認定技術者試験)した、
単体で動くプログラムのテスト-たとえばデバッグによる単一クラスのテスト-
を、通常は「単体テスト」と呼ぶ。
■2.MVVM:
Microsoft の説明が分かりやすい。
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2009/february/patterns-wpf-apps-with-the-model-view-viewmodel-design-pattern
WPFで画面を閉じる処理が課題だったが、こちらを読みながら作成できた。
■3.Prism:
MVVM用のフレームワーク。職場のVSになぜかインストールできない。
■4.Entity Framework:
職場の環境上、Coreではなく、古いエディションのEntityFramework6を利用している。
DAO(そもそもこの言葉をなんとなくでしか理解できてないが)を作成する手間が減る。
■5.非同期処理:
マルチタスク。以前トライしたことはあるものの、効果的な実用には至らずだった。
当時は例外処理に泣いた。
今度は、その思想まで理解して実用化したい。
■6.リフレクション:
型推論というイメージ。
動的コードの利点は、コード量が減ること。
逆に欠点は、目でコードを見て理解することが難しくなること。
開発期間が厳しい、かつプロジェクトメンバーのレベルが高い場合、このリフレクションが選択肢としてあれば心強い。
■7.追記:
2.MVVM、6.リフレクションについては前職で経験済みだが、理解不足と感じているため。
LINQについても以前は比較的利用していたが、人間使わければ忘れてしまう。
今回、EntityFrameworkにて利用する機会があるのはありがたい。

【3】
現在は研修という名目で、DB更新機能を備えたシステムを一人で作成中。
期間は1か月以上と潤沢。
目的は私の実力を把握するためとのことだが、
私自身は次の2つを目標としている;
・最低限の仕様書を残しながら、プロジェクトを計画から大幅な遅滞なく進めること。
・EntityFramework6、およびNUnit3を利用した開発により、開発時間の短縮、品質の向上を図ること。

以上となります。
ここまで読んでいただき、ありがとうございました。

あの日見たScriptableObjectの型を僕達はまだ知らない

ScriptableObjectの読み込みを一元管理する

ScriptableObjectは便利ですよね。データをひとまとまりで取得できる優れものです。
今回はそれを読み込む流れを一元管理したいと思います。

読み込みが管理されていないと、どうなる?

Image2.png
クラスとScriptableObjectが「多対多」の関係になってしまい、人間の脳に優しくありません。

間に管理クラスを挟んで、「1対多」の関係を作る

Image1.png

管理クラス作成のために、ジェネリクスを使う

LoadData.cs
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicsealedclassLoadData{privatestaticLoadDatainstance=newLoadData();publicstaticLoadDataInstance{get{returninstance;}}// ScriptableObjectのみ受け付けるジェネリクスメソッドpublicTScriptableLoader<T>(stringpath)whereT:ScriptableObject{returnResources.Load<T>(path);}}

こうすることで、ScriptableObjectが返されることを保証しつつ、様々な型のScriptableObjectを指定できます。

コード

今回使用したScrptableObjectです。

GameData.cs
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;[CreateAssetMenu(menuName="MyScript/Create GameData")]publicclassGameData:ScriptableObject{publicintData1;publicstringData2;publicfloatData3;}

これをもとに、ScriptableObjectを作成し、値を入れます。
Image4.png

それをStart()で表示してみます。

Game.cs
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassGame:MonoBehaviour{// Start is called before the first frame updatevoidStart(){Debug.Log(LoadData.Instance.ScriptableLoader<GameData>("Data/MyGameData").Data1);}}

実行結果

Image3.png

おわりに

以上、「ScriptableObjectの型は使いたいクラスだけが知っていればいいよね。読み込むクラスはそんなの知らなくていいよ」という話でした。

.NET Core で秘密文字を安全に運用する(開発環境編)

プログラムでの秘密の文字列

業務系のプログラムでは、何かしらのデータベースやストレージのシステムにアクセスし、データの入出力を行います。データベースなどへの接続の際には、アカウント/パスワードといった機密の文字列を使用することが多いと思いますが、これを開発段階からリリース、運用フェーズまで安全に管理するのは意外と大変です。

 プログラムから見た秘密の文字列の置き場所として、昔ながらの iniファイル、レジストリ、.NetFramework の場合は App.config に記述する方法などがありますが、基本的にプレーンテキストですので、扱いには気を使います。うっかりバージョン管理システムの管理対象にしてしまったり、デプロイ先で見つけられてしまうといったリスクがあります。ソースコードに直に埋め込んで、バイナリの中に隠すという方法も、実のところよく聞く話ですが、バイナリエディタで見れば、あっさりバレてしまいます。

 独自のハッシュ化やエンコード関数を自作されている話も聞きますが、他社との共同開発になった時、ライセンシーや、その関数のソースコードを他社と共有する点で課題が発生することになります。

Microsoft の秘密文字ソリューション

 秘密文字の管理のソリューションとして、Microsoft から2つの方法が提供されています。一つは、UserSecret を使う方法で、ローカルPC内の指定のディレクトリ内で管理します。管理場所が決まっていますので、うっかりバージョン管理システムにアップしてしまうこともありませんし、実装方法も簡単ですので、とっつきやすいと思います。ただ、暗号化などは行いませんので、Microsoft からは開発環境用としての位置づけとなっています。

もう一つは、Azure Key Vault を使う方法です。Azure Key Vault は、Microsoft のクラウド Azure のサービスの一つで、秘密の文字列をクラウドで管理します。Microsoft で厳重に管理されており、秘密文字へのアクセスには証明書が必要ですし、アクセスログも記録されます。エンタープライズ製品向けといえます。Microsoft では、UserSecret に比べ本番環境用として位置づけられています。

UserSecret を使った秘密文字の管理

 UserSecret 及び Azure Key Vault での実装方法などを見ていきたいと思います。サンプルプログラムでは、.Net Core のコンソールで行いますが、ASP.NET などでも考え方などは変わりません。

サンプルで使うもの等

  • Visual Studio Code
  • dotnet code 3.1
  • console プログラム
  • Windows/MacOS/Linux

プログラムの準備

dotnet コマンドで新規プロジェクトを作成します。ターミナルから次のコマンドを実行し、コンソールプログラムとして作成しています。

# mkdir vaultsample# cd vaultsample# dotnet new console

パッケージの追加とシークレットマネージャーの初期化

 UserSecrets に関連するパッケージをインストールします。.csproj ファイルがあるパスで次のコマンドを実行します。

# dotnet add package Microsoft.Extensions.Configuration# dotnet add package Microsoft.Extensions.Configuration.UserSecrets

次に、シークレットマネージャーを初期化します。

# dotnet user-secrets init

インストールが完了すると、.csproj ファイルに Key Vault へのリファレンスが記述された ItemGroup と、追加されます。

ASP.NET Core の構成プロバイダーの Azure Key Vault
ASP.NET Core での開発におけるアプリシークレットの安全な保存

<?xml version="1.0" encoding="utf-8"?><ProjectSdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>netcoreapp3.1</TargetFramework><UserSecretsId>07f81c45-c201-4de5-b9ff-96510163b7d6</UserSecretsId></PropertyGroup><ItemGroup><PackageReferenceInclude="Microsoft.Extensions.Configuration.AzureKeyVault"Version="3.1.5"/></ItemGroup></Project>

秘密文字の登録

次のコマンドで秘密文字を登録します。秘密文字は、シークレット名と値の組み合わせで登録します。

dotnet user-secrets set"SecretName""secret_value_1_dev"
dotnet user-secrets set"Section:SecretName""secret_value_2_dev"

なお、削除するときは次のようにコマンドを実行します。

dotnet user-secrets remove "SecretName""secret_value_1_dev"

dotnet コマンドで作成しても構いませんが、格納先は下の通り、ユーザのホーム領域で、JSON 形式ですので、直接編集することもできます。

Windowsの場合
%APPDATA%\Microsoft\UserSecrets\<user_secrets_id>\secrets.json
Linux/MacOSの場合
~/.microsoft/usersecrets/<user_secrets_id>/secrets.json

また、Visual Studio Core の拡張ツール .NET Core User Secretsを使えば、UI 上で操作できます。

プログラムから秘密文字を取得する

 次に、登録した秘密文字列を、プログラムから取得する方法です。秘密文字などの管理には、ConfigurationBuilder を使用します。インスタンス化する際に、AddUserSecretsメソッドを呼び出すことで、UserSecret として登録した秘密文字を取得することができるようになります。

Program.cs
usingSystem;usingMicrosoft.Extensions.Configuration;namespacevaultsample{classProgram{staticvoidMain(string[]args){varcbr=newConfigurationBuilder().AddUserSecrets<Program>().Build();Console.WriteLine($" secret key is {cbr["SecretName"]}");}}}

これにより、

  • 秘密文字 -> ユーザのホームディレクトリ
  • 開発ソースコード -> 開発用ディレクトリ

という運用が可能になりました。

次の投稿で、Azure Key Vault を使用した、さらに安全性の高い秘密文字の運用方法を記載します。

(つづく)

<参考>

【C#】DBの取得と値変更

単一の項目を取得する場合は下記を記述
var1(クラス);var2aList.Single();2.項目名=(変更値);

()varaList=TestClass;vara=aList.Single();a.List+=1;

【C#】用語集

自分が学習する際に調べた用語集 ※随時更新

★オブジェクトとは
・操作や処理の対象になる実体を表す
・オブジェクトの作成には「new」する

test1.cs
vartestObject=newTest();

★クラスとは
・プロパティ(属性)とメソッドを定義するモノ


★インスタンスとは
・クラスを基に具現化されたモノ(newされたモノ)


★コンストラクターとは
・インスタンスを正しく初期化するためのメソッド
・型名と同じ名前でメソッド定義が可能
・戻り値を返すことは不可

test2.cs
classSampleConstructor{SampleConstructor()//コンストラクター{//インスタンスの初期化用コードを記述}}

★メンバー変数とは
・クラス内で宣言される変数

test3.cs
アクセシビリティ変数名;()privateintSample;

アクセシビリティのレベルはこちら


★「this.」
・現在のインスタンスを指定する

Test4.cs
publicTestClass(stringtestThis){this.testThis=testThis;}

【C#】アクセシビリティ レベル

アクセシビリティ

アクセシビリティ内容
publicアクセス制限なし
protectedクラス内、派生クラス内からのみ
internal同一プロジェクト内のクラスからのみ
protected internal同一プロジェクト内のクラス内、または派生クラスの内部からのみ
private protected同一プロジェクト内のクラス内かつ派生クラス内からのみ
privateクラス内からのみ

DI (依存性注入) って何のためにするのかわからない人向けに頑張って説明してみる

ここでは、最近のそこそこの規模のアプリだと大体使われてる(と私は思ってる)Dependency Injection(DI)について、何故使ってるのか?というのを私の理解で書いていきたいと思います。

今回の対象言語は C# ですが、DI 使ってる言語であれば大体同じ事情なのかなと思います。

単体テストしたいよね

アプリケーションを作るとうまく動いているかテストをすると思います。
たとえ、そのアプリがハローワールドだとしても動かして目視で確認してると思います。

もうちょっとアプリの規模が大きくなってくるとクラス単位やクラスのメソッド単位でのテストもしたくなってきます。俗にいう単体テストというやつですね。いちいちアプリを起動して、そのクラスを使う画面まで移動してテキストを入力したりしてボタンを押さないと動かせないのはテスト効率が悪いので、テストコードを書いて実行して緑のバーが出たらテスト成功!そういう環境を作っておくと何かと便利になります。

image.png

コードを変更したときにテストを実行してグリーンだったら少なくともテストコードを書いてる範囲内についてはバグってることは、ほぼないという感じなので安心感が違います。

単体テストをするというのは、世の中全体としてみても「単体テストなんて不要だ!しないほうがいい!」という人はかなり少数派だと思うので、単体テストは出来るならする方が良いというのは多くの人にとって合意してもらえることなのかなと思います。

単体とは…?

テスト書いてみましょう。例えば以下のようなクラスがあるとします。単純ですね。足し算するだけです。

classCalc{publicintAdd(intx,inty)=>x+y;}

色々な単体テストフレームワークがありますが、大体 Assert というクラスを使ってメソッドの結果が思った値と同じか確認します。大体以下のようになります。

varcalc=newCalc();Assert.Equal(10,calc.Add(8,2));// 8 + 2 は 10 になるはず

でも 1 クラスで完結するようなものはなかなかありません。大体クラス内で別のクラスを使ってます。

例えば以下のような感じで DataGenerator クラスで生成されたデータに対して Aggregator クラスで集計(とりあえず合計)するような感じです。

publicclassDataGenerator{publicint[]Generate()=>new[]{1,2,3,4,5,6,7,8,9,10};}publicclassAggregator{publicintSum(){vardataGenerator=newDataGenerator();returndataGenerator.Generate().Sum();}}

Aggregator を単体テストしようとすると DataGenerator が必要ですよね。
今回は DataGenerator は固定値を返すので問題になりませんが例えばインターネット上のデータをもとにデータを生成したり、日付に応じて返すデータが違う場合はどうでしょう?例えばこんな感じです。

publicclassDataGenerator{publicint[]Generate()=>new[]{DateTime.Now.Year,DateTime.Now.Day,DateTime.Now.Second};}

現実には以下のように配列に年月日などの情報を入れて返すようなことはないと思いますが DB の情報によって返す値が変わったり、Web API の結果によって戻り値が変わったり、特定の状態(しかも、その状態になるには、そこそこの手順を踏まないといけない)じゃないとテストしたい値を返さないなど、その時の状況によって結果が異なるようなものが実際には色々あると思います。

そうなると Aggregator のテストはどうすればいいでしょうか?Aggregator は DataGenerator が返す値を集計するのが仕事です。集計処理をテストしたいのに、依存先クラスの実装にひっぱられてテストができないという問題が起きます。

解決方法!!

手段は色々あります。例えばテストしたいロジックだけをメソッドに切り出してテストを行う。

publicclassAggregator{publicintSum(){vardataGenerator=newDataGenerator();returnSumInternal(dataGenerator.Generate());}// こっちをテストするpublicintSumInternal(int[]data)=>data.Sum();}

内部ロジックを public にする点が Aggregator の利用者にとって優しくないですね…。あまりイケてません。

ここら辺から DI の話になってきます。Aggregator は データを Generate 出来る人がいればいいのですが、これが DataGenerator クラスに固定化されているためにテストがしづらいという問題が起きています。じゃぁクラス固定じゃなくて Generate 出来る人であればいいということを表す interface を使うように変更してみましょう。

publicinterfaceIDataGenerator{int[]Generate();}publicclassDataGenerator:IDataGenerator{publicint[]Generate()=>new[]{DateTime.Now.Year,DateTime.Now.Day,DateTime.Now.Second};}

Aggregator は IDataGenerator であれば OK なようにしたいのですが、メソッド内で DataGenerator クラスを new してると実装を切り離すことが出来ないですよね…。

publicclassAggregator{publicintSum(){// インターフェースを導入しても実装を new してたら意味がない…IDataGeneratordataGenerator=newDataGenerator();returndataGenerator.Generate().Sum();}}

じゃぁ new するのは諦めて外部から受け取るようにしましょう。Aggregator を使う人に責任を押し付けます。

publicclassAggregator{// DataGenerator の実装を new するのは外部にお任せpublicAggregator(IDataGeneratordataGenerator){DataGenerator=dataGenerator;}privateIDataGeneratorDataGenerator{get;}publicintSum()=>DataGenerator.Generate().Sum();}

これでやっと Aggregator がテストできるようになりました。こんな感じですね。

publicclassUnitTest1{// テスト用の DataGeneratorprivateclassMockDataGenerator:IDataGenerator{publicint[]Generate()=>new[]{1,2,3};}[Fact]publicvoidTest1(){// テスト時はテスト用の DataGenerator を使うvaraggregator=newAggregator(newMockDataGenerator());// テスト用の DataGenerator は固定値を返すのでテスト出来るAssert.Equal(6,aggregator.Sum());}}

こんな感じで内部で依存先を new するのではなく、外から依存先の実装を設定してもらうという考え方が Dependency (依存性) Injection (注入) になります。Dependency Injection とインターフェースを組み合わせて実装を入れ替える仕組みを入れることで、クラス単体でテストが可能になります。やったね。

例え、1 回呼ぶのに 100 万円かかるような Web API があったとしても、今回のように呼び出す処理を行うクラスに対して interface を定義しておいて、実装を差し替えるようにすれば OK ですね。

interfaceIReallyExpensiveService{stringCall();}classReallyExpensiveService:IReallyExpensiveService{publicstringCall(){// 1 回呼ぶのに 100 万円の外部サービスを呼んでるとする}}classMockReallyExpensiveService:IReallyExpensiveService{publicstringCall(){// テストのときはテスト用の結果を返す実装でいいよねreturn"テスト用の結果";}}

すべて解決?

こんな感じで、テスト時に差し替え可能に出来たほうが嬉しいものに対して interface を定義して実装を外部から設定するようにするといい感じですが、クラスの利用者側視点から見ると割と最悪です。例えば Aggregator を使う場合は Aggregator の他に DataGenerator を new しないといけないです。

以下のような感じですね。

varaggregator=newAggregator(newDataGenerator());

もうちょっと複雑になってくると、1 つのオブジェクトを組み立てるのに、こんな風にコードを書かないといけなくなるかもしれません。

varx=newProductOrderService(newProductRepository(newPostgreSQLConnectionProvider(newSettingsProvider(),)),newOrderManager(newCustomerManager(newCustomerDataAccessor(newSettingsProvider()),)),);

ちょっとこれをやるのは現実的ではないですね…。

DI コンテナ

ということで、オブジェクトの依存関係を外部から設定するようにすると、オブジェクトを組み立てるのが大変になるので、そこを省力化しようというライブラリが登場してきます。

それが DI コンテナです。ほとんどの DI コンテナは、このインターフェースには、この実装クラスを使ってくれというルールを設定しておくと、いい感じにルールに従ってオブジェクトを組み立ててくれます。

イメージとしては以下のような感じです。

varc=newContainer();// Container クラスが DI コンテナだとする// アプリの起動時あたりで、以下のようにアプリで使うインターフェースと実装クラスを登録していくc.RegisterType<ISettingsProvider,SettingsProvider>();c.RegisterType<IDbConnectionProvider,IPostgreSQLConnectionProvider>();c.RegisterType<IProductRepository,ProductRepository>();c.RegisterType<ICustomerDataAccessor,CustomerDataAccessor>();c.RegisterType<ICustomerManager,CustomerManager>();c.RegisterType<IOrderManager,OrderManager>();c.RegisterType<IProductOrderService,ProductOrderService>();// インスタンスが欲しいときは、コンテナから取得varproductOrderService=c.Resolve<IProductOrderService>();

こうすることで、DI コンテナがコンストラクターの引数とかから依存先を解決していって綺麗に組み立てたオブジェクトを返してくれます。便利。

実際にはフレームワークに DI コンテナが組み込まれていることが多くてコンテナのインスタンスを自分で作ったり、コンテナから自分でインスタンスを明示的に取得することは少ないです。利用者がするのは、インターフェースと実装クラスの対応を登録するだけというのが多いです。

まとめ

DI を何故するのか?ということでさくっとまとめましょう。

  • 単体テストを容易にするためにインターフェースに依存するようにクラスを作る
  • 依存先の実装はコンストラクターなどで外部から渡してもらうようにする
  • ↑のように作るとオブジェクトの組み立てが大変になるので、それを省力化するための DI コンテナがある

という感じなので、個人的な感想としては DI しなくても単体テストさえ可能で現実的な労力で実装可能な方法があれば、別に DI コンテナとか DI 使わなくてもいいかなぁとは思ってます。
ただ、黒魔術的なことをしない限りは C# などの静的な型付け言語だとめんどくさいので、今のところおとなしく DI を使うのが現実的です。

おまけとして、DI コンテナを使うことでオブジェクトの生成時に付加価値を追加するようなことも出来るので、フレームワークを提供する側から見ても便利だったりします。まぁ、それは今回の主題とは関係ないのでまた今度。

Win32APIのCreateWindowExでウィンドウ生成に失敗する時の対処法 C#

はじめに

自分の知識を共有するページを書くのはこれが初めてです。
初心者なので稚拙な文章かもしれません。

目的

CreateWindowExでウィンドウを生成する時に、追加したWindowClassを指定すると、ウィンドウの生成に失敗する」
という問題の解決

解決方法

CreateWindowExの値WindowClassNameは byte配列で受け取る。
WindowClassNameに渡す文字列は Unicode で byte配列に変換して渡す。
(実はもう1つある解決方法は一番下に)

[DllImport("user32.dll",SetLastError=true,EntryPoint="CreateWindowEx")]publicstaticexternIntPtrCreateWindowEx(intdwExStyle,byte[]WindowClassName,// byte配列で受け取る。stringWindowName,uintdwStyle,intx,inty,intnWidth,intnHeight,IntPtrhWndParent,IntPtrhMenu,IntPtrhInstance,IntPtrlpParam);voidcreate(){// WindowClassを作成WNDCLASSEXwind_class=newWNDCLASSEX();wind_class.cbSize=Marshal.SizeOf(typeof(WNDCLASSEX));wind_class.WindowClassName="ClassName";wind_class.lpfnWndProc=Marshal.GetFunctionPointerForDelegate(delegWndProc);// 作成したWindowClassを登録するushortregResult=RegisterClassEx(refwind_class);// ウィンドウの生成IntPtrhWnd=CreateWindowEx(0,// Unicodeでbyte配列に変換して渡してあげるnewUnicodeEncoding().GetBytes(wind_class.WindowClassName),"Title",WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,300,400,IntPtr.Zero,IntPtr.Zero,wind_class.hInstance,IntPtr.Zero);}

原因

おそらく、この記事を読んでいる人は
CreateWindowExの定義部分WindowClassNameは string型になっていると思う。

[DllImport("user32.dll",SetLastError=true,EntryPoint="CreateWindowEx")]publicstaticexternIntPtrCreateWindowEx(intdwExStyle,stringWindowClassName,// ここがstringになっているstringWindowName,uintdwStyle,intx,inty,intnWidth,intnHeight,IntPtrhWndParent,IntPtrhMenu,IntPtrhInstance,IntPtrlpParam);

実はWindowClassNameを1文字の string 又は char にしてもウィンドウの生成に成功する。
が、複数文字列の string だと失敗する。
難しいことはあまり分からないが、色々試した結果たどり着いた答えは「文字コードの違い」だった。

もう1つの解決策

CreateWindowExの定義部分で、WindowClassNameの型を string でも byte[] でもなくushortにして、
CreateWindowExを呼ぶ時に、RegisterClassExの戻り値をWindowClassに渡すことでも成功する。

スマートフォンアプリケーション開発について

スマートフォンのアプリケーション開発を勉強し始めたので、勉強をした事を復習の意味も込めて書き残そうと思います。

0.スマートフォンアプリケーション開発

スマートフォンが普及をし始めてから約10年、これまで様々な手法で
アプリケーション(以降アプリ)が開発されてきました。
Windowsアプリの開発しか経験のない私には、スマートフォンのアプリ開発にも興味が沸き、これまでどのような言語があるのか代表的な言語を調べてみました。

1.開発言語

  • iOS
    • Objetive-C

       当初はこの「Objetive-C」を開発言語とされていましたが、
       現在ではSwiftが主流となりつつあります。また、独特な文法表現があるため、
       これからiOS向けの開発を始める人にとっては、Swiftがおすすめです。

    • Swift

       SwiftはAppleが2014年に新しく開発したMacやiOS向けの言語です
       動作するにはXcodeというMacの統合開発環境が必要であるため、
       コンパイルするにはMac端末が必要となります。

  • Android
    • Java

       開発に携わっている人はほとんど聞いたことがある言語「Java」です。
       Androidアプリの多数はJavaで作られています。
       2010年前半は、Javaの開発環境であるEclipseを使用されていましたが、
       現在ではAndroid Studioが使用されています。

  • Windows(UWP)
    • C#

       C#はもともとC言語とオブジェクト指向の要素を持つ言語で、
       Microsoft .NET Framework上で開発をします。
       C++++とも呼ばれましたが、C#のほうがしっくりきます。(笑)

    • VisualBasic

       こちらの言語もC#と同様、.NET Framework上で開発をします。
       もともとはBASIC言語から派生した言語でした。BASIC6.0までは
       オブジェクト指向の要素を持っていなかったがVisualBasic.NETでは
       その要素も実装されており、C#に劣らない言語です。

2.まとめ

各言語を使えばそれぞれのプラットフォーム上でアプリを開発することはできますが、
クロスプラットフォームをターゲットとしたい場合は各言語で開発する必要がでてきます。

面倒なので私は絶対に嫌です!(笑)
クロスプラットフォーム上で動作する言語があれば開発が便利になりますね!

【Unity/C#】ノームソートとは(コード付き)

ノームソートとは

ノームソートはソートアルゴリズムの一種で、挿入ソートに似ているが、要素の移動は挿入ではなくバブルソートのような一連の交換で行う。その名称の由来は、オランダのノームが一列に並んだ鉢植えの花をソートする話である。

実行結果

ノームソート.gif

サンプルコード

voidGnomeSort(int[]_array){intgnome=1;while(gnome<_array.Length){if(_array[gnome]<_array[gnome-1]){_array[gnome-1]^=_array[gnome];_array[gnome]^=_array[gnome-1];_array[gnome-1]^=_array[gnome];gnome--;if(gnome==0){gnome++;}}else{gnome++;}}}

【C#】例外処理クラス一覧

クラス名throw条件
名前空間:System--------
ArgumentExceptionメソッドの引数がない
ArgumentNullExceptionやArgumentOutOfRangeException以外
ArgumentNullException引数がNull
ArgumentOutOfRangeExceptionメソッドの許容範囲外の値が引数として渡された
ArithmeticException算術演算によるエラーの基本クラス
OverflowException,DivideByZeroException,NotFiniteNumberException以外の算術エラーを示したいとき
OverflowException算術演算やキャストでオーバーフローが起きたとき
DivideByZeroException0で割ったとき
NotFiniteNumberException浮動小数点数値が無限大のとき
FormatException引数の書式が仕様に一致していない場合
IndexOutOfRangeException配列のインデックスが異常なとき
InvalidCastException無効なキャストのとき
InvalidOperationException引数以外が原因のとき
ObjectDisposedExceptionDispose済みのオブジェクトで操作が実行されたとき
NotImplementedExceptionメソッドが未実装の場合
NotSupportedException呼び出されたメソッドがサポートされてないとき
もしくは呼び出された機能を備えておらず、ストリームに対して読み取り、シーク、書き込みが試行されたとき
NullReferenceExceptionNullオブジェクト参照を逆参照しようとしたとき
PlatformNotSupportException特定のプラットフォームで機能が実行されないとき
TimeoutException指定したタイムアウト時間が経過したとき
名前空間:System.Collections.Generics--------
KeyNotFoundExceptionコレクションに該当するキーがないとき
名前空間:System.IO--------
DirectoryNotFoundExceptionディレクトリが存在しないとき
FileNotFoundExceptionファイ府が存在しないとき
EndOfStreamExceptionストリームの末尾を超えて読み込もうとしたとき

【C#】try-catch

・tryブロックには例外1の可能性がある処理を記述
・catchブロックには例外1が発生した場合の処理を記述
・finallyブロックには例外1の有無関わらず実行する処理を記述

try{//例外発生の可能性のある処理を記述}catch{//例外が発生した場合の処理を記述}finally{//例外の発生有無に関わらず実行する処理を記述}


(例)

Test.txt
ささみの味噌煮
trycatch.cs
usingSystemclassSampleTryCatch{staticvoidMain(){StreamReadersr=null;try{sr=newStreamReader(@"D:Test.txt",Encoding.GetEncoding("Shift_JIS"));stringstr=sr.ReadToEnd();Console.WriteLine(str);}catch(IOExceptione){Console.WriteLine("例外が発生しました。");Console.WriteLine(e);return0;//またはスルーさせる//throw;}finally{if(sr!=null){sr.Close();Console.WriteLine("ファイルを閉じました");}

実行結果

ささみの味噌煮
ファイルを閉じました

  1. 例外クラスの一覧はこちら 

【C#】LINQ

★LINQの使い方

・LINQには標準でIEnumerable、IEnumeratorが実装されている
・データを問い合わせることを可能にした機能

LINQの記述方法
◇クエリ構文 
・from句が必要で、from句から始める
・終わりがselect句かgroup句で終了
・ループ処理は発生しない

QueryLinq.cs
vartest1=fromaintestwherea*2==0selecta;


◆メソッド構文
・from句が不要
・メソッドベースの構文

MethodLinq.cs
vartest1=test.where(a=>a*2==0).select(a=>a);

★遅延評価
・LINQの特徴に遅延評価というのが存在する。
・基本的にはクエリ式は即時評価されない。1
・クエリ変数がforeachなどの反復処理によって評価されるまでクエリの実行は遅延する


  1. 遅延評価の逆は正格評価(先行評価)といい、即時評価される 

C# で前前前世

Delphi で前前前世 - Qiitaを C# でやってみました。拡張メソッドがあるので簡単ですね。

usingSystem;namespaceConsoleApp1{staticclassProgram{staticvoidMain()=>then().then().then().();publicstaticstringthen()=>"".then();publicstaticstringthen(thisstringprev)=>prev+"前";publicstaticvoid(thisstringprev)=>Console.WriteLine(prev+"世");}}

出力

前前前世

踊り字を使ってみる。

usingSystem;usingSystem.Linq;namespaceConsoleApp1{staticclassProgram{staticvoidMain()=>then().then().then().();publicstaticstringthen()=>"".then();publicstaticstringthen(thisstringprev)=>prev+(prev!=null&&"前々".Contains(prev.LastOrDefault())?"々":"前");publicstaticvoid(thisstringprev)=>Console.WriteLine(prev+"世");}}

出力

前々々世

まあ Console.WriteLineをこんなところに入れてる時点で気持ち悪いんですが。

unityでとりあえずプレイヤーを動かすスクリプト

始めに

フライトゲームやFPSでプレイヤーを動かすスクリプトを書きました。
プレイヤーの動かし方が分からない人は必見です!
(これはmacで開発することが前提となっています)

下準備

  1. unityのnewを選択 スクリーンショット 2020-02-16 20.28.41.png
  2. Project nameを決めてCreate projectを押すスクリーンショット 2020-02-16 20.31.50.png
  3. Create -> 3D Object -> Planeをクリック、地面を作ります。 スクリーンショット 2020-02-16 20.45.42.png
  4. Create -> 3D Object -> Cube、今回はこれを動かします。 スクリーンショット 2020-02-16 20.46.41.png
  5. Cube -> Add Componentをクリック'Rigidbody'と検索Rigidbodyをクリックして追加する スクリーンショット 2020-02-16 20.54.18.png
  6. Main CameraをドラクアンドドロップでCubeに入れる
    スクリーンショット 2020-02-16 20.59.28.png
  7. ProjectのCreateからC#Scriptを選択してクリック
    スクリーンショット 2020-02-16 21.03.09.png
  8. デリートキーを押し、'Player_controller'と入力
    スクリーンショット 2020-02-16 21.05.14.png
  9. 作成したスクリプトをダブルクリックで開く スクリーンショット 2020-02-16 21.13.27.pngこれで下準備はOKです。

スクリプト

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassPlayer_controller:MonoBehaviour{// Start is called before the first frame updatevoidStart(){}// Update is called once per framevoidUpdate(){if(Input.GetKey(KeyCode.UpArrow)){transform.position+=newVector3(0,0,0.1f);}if(Input.GetKey(KeyCode.DownArrow)){transform.position+=newVector3(0,0,-0.1f);}if(Input.GetKey(KeyCode.RightArrow)){transform.position+=newVector3(0.1f,0,0);}if(Input.GetKey(KeyCode.LeftArrow)){transform.position+=newVector3(-0.1f,0,0);}}}

開いたプログラムの内容を全て削除して上のスクリプトをコピペしてコマンドSで保存。unityに戻りこのスクリプトをCubeにドラクアンドドロップをする。
これで上の三角のボタンを押せば終了です。
もし、Cubeにスクリプトを入れられなかったらスクリプトを右クリック -> Remameを押して'Player_controller'と入れてみてください!

最後に

最後まで見てくださってありがとうございます。
Qiitaは始めたばかりなので間違っていたら遠慮なく指摘してください!よろしくお願いします。

unityで音を鳴らそう!

始めに

この記事の対象者
- 製作中のゲームに音を入れたい人
- unityに興味がある人

下準備

  1. unityのプロジェクトを開く スクリーンショット 2020-02-17 20.04.08.png
  2. Create -> Create Emptyを選択してCreate Emptyを生成する スクリーンショット 2020-02-17 20.05.17.png
  3. Create(Project) -> C# Scriptを洗濯して新しいスクリプトを生成する スクリーンショット 2020-02-17 20.06.01.png
  4. スクリプトを右クリックしてRemameを選択'sound_script'と入力してダブルクリック スクリーンショット 2020-02-17 20.12.04.png
Browsing Latest Articles All 1943 Live