Continuousで始めるC# / Xamarin 005 寄り道 ( Draft )
.NETってなんなん?
.NETという言葉はよく聞くけど実体はよく知りませんでした。
ネイティヴではなく、Javaのような仮想環境上で動くとか、なので、CPUに依存しないとか、アプリがWindowsでもWindows Mobileでも動くとか、その分遅いとか、そういうレベルの知識しか持ってなく。なぜ、わざわざ遅くなるやり方するのかなぁとか、セキュリティ的にはいいのかもなぁとか思っていました。
で、C#を始めるにあたって、色々と読んでいると、.NETとかそれがらみの言葉が大量に押し寄せてくるので、ちょっと調べたりしてみました。知っている人には、そんなこと?という内容かもしれません。
なぜC#を作ったのか
.NET以前、MicrosoftはWindows上でのソフトウェア開発手段として、Visual Basic と Visual C++ を提供していました。特徴を簡単に書くとこんな感じ。
- Visual Basic
- 割と簡単に作れる。
- 高度なアプリは作れない。
- Visual C++
「どっちで作ればいいの?」という問いに対しては答えにくい状態でした。で、Microsoftが目をつけたのがJavaでした。
MicrosoftはJavaを使ってWindowsのアプリを作れるように、Visual J++を開発しました。しかしながら、当時のSun Microsystemから「Javaは特定のOSに依存しちゃダメ」とライセンス違反を突き付けられ、裁判にも負けてしまいました。
そこて、自らの手でJavaみたいな言語を作ることにしたのです。それがC#というわけです。
お、同じやんか。
そして、Visual Basicも、Visual Basic .NETとして、同じように生まれ変わります。文法が異なる以外は同じ特徴を持ちます。
C#でアプリを書いても、Visual Basicでアプリを書いても、コンパイルすると同じ中間言語MSILになって実行されます。
ちなみに、C#の父と呼ばれるアンダースヘルスバーグ ( Anders Hejlsberg ) は、昔、ボーランドという会社でTurbo PascalやDelphiの開発をしており、その後、Microsoftに行き、Visual J++を開発。その後、C#を開発しました。C#の文法をみるとナルホドと思ってしまいますね。
Continuousで始めるC# / Xamarin 004 [ Draft ]
メソッドのオーバーロード
引数の個数や型が異なるけれど同じ名前のメソッドを作ることをメソッドのオーバーロードと言います。前回作ったコンストラクタは、以下のように、firstName, lastName, bloodTypeという3つの文字列を渡していました。
public Person( string firstName = "unknown", string lastName = "unknown", string bloodType = "unknown" ) { FirstName = firstName; LastName = lastName; BloodType = bloodType; }
もうすでにPersonクラスのインスタンスがあって、これと同じインスタンスを作りたい場合は、もとになるPersonのインスタンスを渡せるコンストラクタがあると便利ですね。
ということで、書いてみると以下のようになります。メソッド名は同じですが、引数リストが異なるため二重定義のエラーになることはありません。
public Person(
Person person
) {
FirstName = person.FirstName;
LastName = person.LastName;
BloodType = person.BloodType;
}
呼び側のコードは以下のとおり。
Person p1 = new Person( firstName : "Taro", lastName : "Ito" ); // p1の複製を作る Person p2 = new Person( p1 );
静的フィールドや静的メソッド
例えば、全てのPersonのインスタンスにユニークなidを付けたいとします。コンストラクタが呼ばれるたびに0から1ずつカウントアップしてidにしましょう。
この値を保持するのは、インスタンスの中では都合が悪いので、クラス自身に持つことになります。クラス内のグローバル変数のようなものですね。
この場合、フィールドの宣言の先頭にstaticと書きます。
public class Person { // *1 クラスに属するフィールド static private int id = 0; // *2 クラスに属するメソッド / プロパティ public static int Id { get { return id; } } public Person( string firstName = "unknown", string lastName = "unknown", string bloodType = "unknown" ) { FirstName = firstName; LastName = lastName; BloodType = bloodType; id++; // *3 カウントアップ }
- 1 : この例ではstatic privateとしていますので、外からは見えませんが、static publicとすれば、Person.idでアクセスできるようになります。CLASS_NAME.FIELD_NAMEでアクセスできます。
- 2 : フィールドを生で公開したくなければ、staticなメソッド、もしくはプロパティを作ればよいです。Person.Idで値を取得できます。CLASS_NAME.METHOD_NAMEの形ですね。
Continuousで始めるC# / Xamarin 003 : Hello World
C#のザックリ解説
ちゃんとC#を勉強するには本を1冊以上読むことになるかと思いますが、ここでは、プログラミング経験のある方向けに、C#の雰囲気を見てもらうレベルのザックリ解説を行います。
C#は、JavaとかC++とかObject Pascalとかに影響を受けている言語とされています ( Object Pascalって何?とか言わない )。文法は、既存の言語に合わせられる部分はそのまま流用している感じで、経験のある方なら基本的なところはすんなりと理解できるのではないかと思われます。
HELLO WORLDしてみる
HELLO WORLDは以下のような感じになります。この後、アドレス帳っぽい感じにしていくので、クラス名などはそういう名前にしています。
// 基本のライブラリを使用 *1 using System; // アプリのコードはこの名前空間に入れる *2 namespace App { // アドレス帳アプリのクラス定義 *3 public class AddressBookApp { // Mainが実行される *4 public static void Main( string[] args ) { // コンソール出力 *5 Console.WriteLine( "HELLO WORLD" ); } } }
とりあえず、コンソールに文字列を出すだけですので、細かい説明は後回しで構成を見ていきます。
- 1 : usingはライブラリの使用の宣言でもありますが、オブジェクト名を簡潔に書くためのものでもあります。例えば、コンソール出力は、System.Console.WriteLineですが、Systemが省略可能となります。
- 2 : namespaceで名前空間を宣言しています。クラス名等の衝突を避けるための殼を作ることができます。関連するクラスの定義をまとめるためのものでもあります。
- 3 : アドレス帳アプリのクラスの定義をここに定義します。クラスの定義は public class CLASS_NAMEのように書きます。外から見えなくしたければpublicのところをprivateにします。継承したいクラスは今回ないので省略しています。といっても、省略するとルートクラスのObjectを継承します。
- 4 : Mainメソッドを書いておくと、ここから実行されます。
- 5 : Console.WriteLineでコンソール出力します。自動で改行されます。
独自クラスを作ってみる
アプリの外枠を作りましたので、アドレス帳を管理するライブラリとしてAddressBookKitというのを作ります。
using System; // アドレス帳のライブラリを使う using AddressBookKit; // アドレス帳のライブラリ namespace AddressBookKit { // Personクラスの定義 *1 public class Person { // フィールドの宣言 *2 public string FirstName; public string LastName; public string BloodType; // コンストラクタの定義 *3 public Person( string firstName, string lastName, string bloodType ) { // 中身を初期化 FirstName = firstName; LastName = lastName; BloodType = bloodType; } // インスタンスメソッドの定義 *4 public string GetFullName() { // 文字列生成 *5 return String.Format( "{0} {1}", FirstName, LastName ); } } } // アドレス帳アプリ本体 namespace App { public class AddressBookApp { public static void Main( string[] args ) { // Personクラスのインスタンス生成 *6 Person p1 = new Person( "Hanako", "Yamada", "B"; ); // フィールドを変更 *7 p1.FirstName = "Taro"; p1.LastName = "Suzuki"; // メソッド呼び出し *8 Console.WriteLine( "FullName={0}", p1.GetFullName() ); } } }
- 1 : 人のデータを扱うPersonクラスを作っていきます。変数宣言は、TYPE NAME のように書きます。
- 2 : オブジェクトの中に情報を保存するにはフィールドを宣言します。public string FIELD _NAMEのように書きます。publicのところはクラスと同じです。stringは、フィールドの型で文字列を表します。整数ならintになります。
- 3 : インスタンスを生成するためのコンストラクタは、クラス名と同じ名前のメソッドとして定義します。public CLASS_NAMEで始まり、引数リスト、処理の中身が続きます。メソッド名の前には、通常、そのメソッドの返り値の型を書きますが、コンストラクタの場合はそのクラスだと決まっているため不要です。
- 6 : 先にコンストラクタを呼んでいるところを見てみますと、new CLASS_NAMEに続いて引数リストを書くことでインスタンスを生成できます。
- 4 : インスタンスのメソッドを1つ定義してみます。GetFullNameというフルネームを返すものです。
- 5 : String.Formatというのは書式指定で文字列を生成するメソッドです。{N}は、文字列の後ろにある値を埋め込む場所で、Nには何番目の値を使うかを書きます。{0}だと、文字列の直後のFirstNameの中身に置き換わります。この書式指定はConsole.WriteLineでも使えます。
- 7 : 生成したインスタンスのフィールドのアクセスにはドットをつけてフィールド名を書きます。
- 8 : メソッド呼び出しも、ドットをつけてメソッド名。その後ろに引数リストを書きます。
大体、どこかで見たことあるような文法ばかりですね(個人的感想)。
引数のデフォルト値
クラスにメソッドを色々と実装する際に、機能は同じでも、簡単に使える引数の少ないメソッドと、詳細を指定できる引数の多いメソッドを用意したくなります。でも、何通り作ればいいのか悩みますよね。
C#では、メソッドを呼び出す時に引数を省略してもいいような仕組みを持っています。省略された引数に対してデフォルト値をメソッド側で決めておくことができるのです。
以下のように引数のデフォルト値をイコールの後ろに書きます。
// デフォルト値指定付きの引数 *1 public Person( string firstName = "unknown", string lastName = "unknown", string bloodType = "unknown"; ) { FirstName = firstName; LastName = lastName; BloodType = bloodType; }
呼び側は以下のように引数の名前を書きます。名前がないと、どれが省略されたか分からないからですね。
Person p1 = new Person( firstName : "Hanako", lastName : "Yamada" );
引数に名前を付けた方が可読性が上がるというメリットもあります。
名前があるため、引数の順番を変えても問題ありません。名前を付けているということで、引数リストというより、引数辞書という感じですね。
Person p3 = new Person( lastName : "Sato", firstName : "Jiro" );
プロパティ
先程、GetFullNameというメソッドを定義しましたが、メソッドだと、呼び出し側はp1.GetFullName()のように末尾に括弧をつけて呼ぶことになります。でも、このような単なる情報取得の場合は、フィールドにアクセスする感じでp1.FullNameのように書けるとスマートです。
これを実現するための仕組みがプロパティです。中身はメソッドですが、呼び側から見るとフィールドのように見えます。
プロパティの定義は、メソッドの定義のような書き始めになりますが、引数リストがありません。取得用のメソッドはget { ... }のように書きます。
public string FullName { get { return String.Format( "{0} {1}", FirstName, LastName ); } }
これでp1.FullNameが使えるようになります。
Personクラスに年齢の情報を追加したとします。単にフィールドで追加してもいいですが、マイナスの値がセットされないようにしたいなどの処理が必要な場合はメソッドになりますよね。
これをプロパティを使うと次のようになります。
public class Person { : int age; // フィールドの宣言 *1 // プロパティの定義 *2 public int Age { get { return age; } set { if ( 0 <= value ) { age = value; } } } }
- 1 : 値を保持するフィールドを宣言します。プロパティ経由でこのフィールドを書き換えますので、privateにします。デフォルトがprivateなので、何も書かないとprivateになります。
- 2 : プロパティの定義のですが、値をセットする方はset { ... } のように書きます。valueという変数には、セットされる値、つまり代入文の右辺の値が入っています。
呼び側は以下のようになります。メソッドを呼んでいるのですが、フィールドへの代入のように書けます。
p1.Age = 10;
自動プロパティ
プロパティを知ってしまうとフィールドはあまり使いたくなくなるかもしれません。でも、全てのフィールドに同じコード書くのも面倒ですよね。そのため、短く書ける記法が用意されています。
public string Address { get; set; } // *1 public string BloodType { get; private set; } // *2
- 1 : { get; set; } と書くだけでよく、値を格納するためのprivateなフィールドの宣言も不要です。意識する必要はありませんが、内部的にフィールドが自動生成されます。
- 2 : クラスの中からはセット可能で、外部からはセットはできないプロパティは、private set とします。例えば、血液型は後からは変わらないので、コンストラクタでのみ値が指定できるようにしたい場合に使えます。何らかのidなどで変えられないようにしたいとかですね。
なんかこう、Swiftに似てるよね(逆)。
Continuosで始めるC# / Xamarin : 002 Script
Scriptというお手軽開発機能
iPhone上でプログラムを動かせるというだけでもお手軽ですが、ContinuousにはScriptというお手軽開発機能があります。
C#はコンパイル言語ですが、Continuousではスクリプト言語のようにも動かせます。プロジェクトとかソリューションとかのファイルも必要無く、ソースファイル単体で動作します。
早速試してみましょう。まず、[ + ] アイコンをタップして新規作成します。
[ File ] → [ C# ] → [ Script ] と順にタップ。
ファイル名を決めて [ Create Script ] をタップしたら準備完了です。C#では、ファイルの拡張子はcsですが、Scriptだとcsxになるようです。
クラス定義も不要
C#のプログラミングは、クラス定義をして、中にMainメソッドを書くところからスタートするのですが、スクリプトの場合は、そういうのはなしで、ベタにコードを書いていけます。
以下のコードを入力してみましょう。プログラミングの経験のある方なら、C#の文法の説明は不要ですよね?
using System; int a = 4; double b = (double) a / 3; string c = "HELLO"; Console.WriteLine( c + " WORLD" );
入力して少しすると、実行されて各行の実行結果は、その行の右側に表示されていきます。これがAuto Runの機能です。Auto Runを切っているときは、画面上部の [ ▶︎ ] ボタンを押すと実行されます。
コンソール画面も確認してみましょう。ちゃんと出力されてますね。
Scriptでユーザーインターフェイスを表示
実は前回のIntroductionのマップのサンプルもScriptでした。下図のような画面でした。つまり、Scriptからもユーザーインターフェイスが出せるんです。
これだけのコードで地図表示が出来ます。実質1行です。
using System; using Foundation; using UIKit; using CoreGraphics; using CoreLocation; using MapKit; var Main = new MKMapView( new CGRect( 0, 0, 320, 100 ) );
Mainという変数にUIViewをセットすると画面に表示されるようです。
Continuousで始めるC# / Xamarin : 001 Introduction
プログラミング言語の勉強スタイル
新しいプログラミング言語を覚える時、皆さんはどのように勉強するでしょうか。明確な目的がある時はガッツリと集中して勉強するでしょうし、「何となく面白そうだから試してみよう」位の時はのんびりと勉強することもありますよね。
例えば、通勤/通学電車の中でプログラミング言語の本を読んで勉強することもあると思います。すると確実に「このコード実際に動かしたい!」と思うことになります。
こんな場合に役に立つのが、iPhone上で動く開発環境です。覚えたばかりの知識でコードを書いて動かすというのは楽しいものです。
MicrosoftがXamarinを買収!
さて、急に話が変わりますが、2016年2月MicrosoftがXamarinの買収を発表しました。
当時、私はXamarinという言葉も知りませんでしたが、Windows / macOS / Android / iOS のアプリが書けるマルチプラットフォームの開発環境ということを知り興味津々。
とはいえ、自分はマルチプラットフォームの開発環境に興味はありましたが、Windowsのみで動くアプリを作ることにはあまり興味が無く、C#とか.NETは自分には関係ないものと思っていましたので、ほとんど知識無し。MacにXamarin Studioをインストールしたものの、放置気味でした...。
しかし、iPhone上のC# / Xamarinの開発環境のContinuousというアプリがリリースされたことを知り、早速ゲット。通勤電車内でC#を勉強し始めたのです。
Continuousってどんなアプリ?
Continuousは、iPhone上で動くC#とF#の開発環境です ( この記事ではF#には触れません )。iPhone上の開発環境というと、コンソールに文字列出して終わりというものも多いのですが、Continuousは、ユーザーインターフェイス(UI)も作ることが出来ます。
1200円と安くはないものの、値段に見合うレベルでシッカリと作られている印象です。
Official Site : Continuous C# and F# IDE for iPads and iPhones
画面は以下のような感じです。シンタックスハイライトされていて見やすいですね。
設定画面を先に見ると、文字の大きさとDark Modeというのがあります。自分はDark Modeで使っています。Auto Runは、入力したコードをバックグラウンドでコンパイルして即座に実行するもののようです。
Xamarinって何?
Microsoftが、Windows用のソフトウェアを作るために作った新しいプログラミング言語がC#であり、ソフトウェアを作るために便利なフレームワークとして作ったのが.NET Framework。他にも様々な技術がありますが、これらをまとめて.NETというみたいです。
この.NETの技術を他のOSでも使えるようにしたのがXamarinです。WindowsでC#でMyApplicationを作っても、Xamarinがあれば、他のプラットフォームでも動くようになるのです。
この手のマルチプラットフォームの開発環境では、UIを操るところだったり、カメラだったり、GPSだったりも共通コードになるの?という疑問が湧いてきます。
UIに関してはXamarin.Formsというフレームワークを使うことでコードを共通化出来ます。でも、これを書いている時点では、まだ発展途上という感じでしょうか。比較的シンプルなアプリには使えそうです。
逆に、Xamarinでは、各OSが持っているAPIをC#から直接呼び出せるようになっています。これをXamarin Nativeといいます。コードの共通化は出来なくなりますが、そのプラットフォームの作法に沿ったアプリとして作り込めるというメリットもあります。
データ操作のような部分は、モジュール化してソースを共通化。UIなどはプラットフォーム別に作り込むというやり方です。もちろんプログラミング言語はC#ですので、SwiftとJavaを両方覚えなくて済むというメリットもあります。
上の画像の矢印のところに、以下のコードがあります。usingは、C#での使用するライブラリの指定で、これで、iOSのFoundationとUIKit、そして、Xamarin.Formsも使用しているのがわかりますね。
using Foundation; using UIKit; using Xamarin.Forms;
MapKitを使ったサンプル
Continuousに入っているサンプルコードにMapKitを使った地図表示のアプリがあります。コードは1画面に入る程度のものです。プログラミング言語はC#ですが、iOSのコードという見慣れないと少し不思議な感じですね。
目玉アイコンのタブに切り替えると、UIと各変数の値を確認できる画面になります。ブレークポイントは付けられないので、トレース実行は出来ないようです。
矢印のアイコンでUIをフル画面に切り替えることも出来ます。
コンソールを見るためのタブもあります。
次回は簡単なコードを動かしてみたいと思います。