[Swift]WinでやるC#erの為のSwift基本文法覚書

# なぜSwiftなのか
C#信者な私ですがiOS/macOSプログラミングをしてみたいのと
*プログラミングは目的ではなく手段*という心が芽生え始めたから
仕事でも趣味でも今まで主にC#を使ってきてたため主にC#との比較になると思います
まだSwift触り始めて2日なので間違っていたり追記したいものがありましたらお気軽にコメント or 編集リクエストお願いします

# 環境
・Windows 10 64bit Pro
・[IBM Swift Sandbox](https://swift.sandbox.bluemix.net/#/repl)
未だMac環境を持たないのでブラウザベースで動作を確認しつつやっていきます

# そもそもSwiftとは
Apple社が開発したネイティブアプリケーションを開発するための言語
元々はiOSとmacOS向けでだったが2015年にオープンソース化されUbuntu向けにもリリースされた
Windows向けも非公式プロジェクトとして動いている模様
（Bash on Ubuntu on Windowsを使えばUbuntu版Swiftが使えるとか使えないとか）

## 変数宣言
C#と違って先頭に型ではなくvarが来る
型を明示する場合は`var 変数名:型`と書く
**追記 C#にも変数宣言時に型推論を表す`var`キーワードがあるがSwiftでの変数宣言は固定で`var`**

```swift:var.swift
//型を明示
var message: String = "Hello Swift !"

//型を推論
var message2 = "Hello Swift !"
```

## 定数宣言
C#で言う`constほにゃらら`
先頭にletとつけて後は変数宣言と同じように

```swift:let.swift
//型を明示
let message: String = "Hello Swift !"

//型を推論
let message2 = "Hello Swift !"
```
## キャスト
C#と違って`(型名)値`という形は使えないようです
`as`を使いますが、C#の`as`に相当する機能は`as?`のようです

```swift:cast.swift
class GameConsole {}
class XBOXOne : GameConsole {}
class PS4 : GameConsole {}

let xbox: GameConsole = XBOXOne()
let ps4 = PS4()

let downCast = xbox as XBOX //ダウンキャストの為エラー
let upCast = ps4 as GameConsole //アップキャストの為OK
let tryDownCast = xbox as? XBOX //ダウンキャストを試行し成功した場合はOptional型、失敗した場合はnilを返す
let tryCast = xbox as? PS4 //XBOXはPS4にはなれないのでnil(逆もまた然り)
let tryDownCast2 = xbox as! XBOX //強制的にダウンキャストを行う。失敗したときは実行時エラー
```

## プロパティ
C#と同じような機能だがどうやら自動実装プロパティが無いらしい `{get;set;}に相当するもの`
setアクセサではC#の`value`の代わりに`newValue`を使用する
**追記 : C#には無い機能としてこれからセットされるのを通知する`willSet`とセットされたのを通知する`didSet`が存在する**

```swift:property.swift
var _Name: String = ""
var Name: String
{
	get
	{
		return _Name
	}
	set
	{
		_Name = newValue
	}
}

Name = "ABC"
print(Name) // -> ABC

Name = "DEF"
print(Name) // -> DEF
```
## 型チェック
C#と同じで`is`を使用する

```swift:check.swift
print(true is Bool) // -> true
print("Hello Swift" is String) // -> true
print("10" is Int) // -> false
```

## Optional型
キャストの方でちらっと出てきた`Optional`型
C#ではクラスであれば大方`null`を入れることが可能だが、
Swiftでは`nil`(nullに相当するもの)は入れることが出来ないので
入れれるようにするのがこの`Optional`型
(C#のnull許容型`int?`のようなもの)

```swift:optional.swift
var optional: Optional<String> //この段階でnil
var optional2: String? //こちらでもOK
```

### アンラップ
上記の`String?`は`String型`とは似て異なるものの為
Stringとして扱うにはOptional型を外す必要がある
方法はいくつかあります

- Forced Unwrapping - 強制的に

```swift:force_unwrap.swift
var msg: String?
msg = "Hello Swift"
var unwrap_msg: String = msg! // !を使うことで強制的にString?からString型にアンラップ msgの中身がnilだった場合は実行時エラー
print(unwrap_msg) // -> Hello Swift
```

- Optional Binding - ifと組み合わせて安全に

```swift:optional_unwrap.swift
var msg: String?
msg = "Hello Swift"

if let unwrap = msg //if let構文を使う事でnilの場合はfalse、アンラップ可能な場合はtrueでif文の中身を実行する
{
	print(unwrap) // -> Hello Swift
}

guard let unwrap2 = msg else
{
	return //guard let ~ else ~ はnilの場合にguardブロックに入る、入った場合はreturnやthrowなどで抜ける必要がある
}

print(unwrap2) //guardを無事抜けれた場合はunwrap2にはアンラップが成功したものが入っていることが保証されるため安全に使用可能
```

- Optional Chaining - C#でもおなじみ

```swift:chaining_unwrap.swift
class GameConsole
{
	var Name: String = "Switch"
}

var NSwitch: GameConsole?
NSwitch = GameConsole()

if let console_name: String = NSwitch?.Name //NSwitchがnilでない場合のみ.以降を実行nilの場合はnilを返す
{
	print(console_name) // -> Switch
}
```

- Implicitly Unwrapped Optional - 暗黙的なアンラップ

```swift:implicit_unwrap.swift
var msg: String!
msg = "Hello Swift"
var unwrap_msg: String = msg //!はつけなくてもOKだがmsg = nilの場合は実行時エラー
print(unwrap_msg) // -> Hello Swift
```

## null合体演算子
C#のnull合体演算子と全く同じ書き方ができる`??`が存在します

```swift:null.swift
let maybeA: Int? = nil
let maybeB: Int? = 0
let a = maybeA ?? 1 // maybeA が nil なので a == 1
let b = maybeB ?? 1 // maybeB が 0 なので b == 0
```


## if文
C#と違ってカッコ`()`は不要
~~逆にカッコを使うときもあるのか…？~~

```swift:if.swift
if 1 == 1
{
	print("true") // -> true
}
```

### 範囲演算子
`a...b`
`a..<b`
上記の二種類があり、
上はa **以上** b **以下**
下はa **以上** b **未満**
if文では`if case a...b = c`という風に使います(cがa以上b以下の場合true)
C#にはこれ相当の機能は無いですね…

```swift:range.swift
if case "か"..."ん" = "を"
{
	print("[を]は[か]～[ん]の中にあります")
	// -> [を]は[か]～[ん]の中にあります
}
```

**@lovee さん提供**
加えてif文では`if case (a...b).contains(c)`という書き方もできます
（if文に於いてはこちらが主流なようです！）

## 関数
`func 関数名(引数) -> 戻り値の型`という形
~~-> って最近C++11か14辺りで似たようなの無かったっけ~~
引数は`引数名: 型名`と書き、呼び出し側では明示的に`func(引数名: 引数の値)`と書く必要がある
明示的に書くのが面倒な場合は関数宣言時に`_ 引数名: 型名`と`_(アンダースコア)`を付けると呼び出し側で明示的に指定する必要が無くなる
`例)func("hogehoge")`

```swift:func.swift
//引数・戻り値無し
func hogeFunc()
{
	
}

//引数有（呼び出し側で引数を明示的に指定する必要がある）
func hogeFunc2(name: String)
{
	print(name)
}

//引数有（呼び出し側で引数を明示的に指定する必要はない）
func hogeFunc3(_ name: String)
{
	print(name)
}

//戻り値あり
func hogeFunc4() -> String
{
	return "Hello hogeFunc4 !"
}

//デフォルト引数
func hogeFunc5(_ name: String = "hogeFunc5")
{
	print(name)
}

hogeFunc()
hogeFunc2(name: "Hello hogeFunc2 !") // -> Hello hogeFunc2 !
hogeFunc3("Hello hogeFunc3 !") // -> Hello hogeFunc3 !
print(hogeFunc4()) // -> Hello hogeFunc4 !
hogeFunc5() // -> Hello hogeFunc5 !
```

## 参照渡し
C#と同様classは全てデフォルトで参照渡し、
structは全てデフォルトで値渡し（コピー）だが
値型を参照で渡したい、参照型を参照渡し（参照先の入れ替え）をしたいという場合は inout を使用すれば可能
渡す側の変数には頭に`&`を付ける

```swift:inout.swift
func Assign(_ numeric: Int,_ variable: inout Int)
{
	variable = numeric
}

var result: Int = 0
Assign(100, &result)
print(result) // -> 100
```

## アクセス修飾子
C#では`public` `protected internal` `protected` `internal` `private`
の5種類で明示的に指定しなかった場合はprivateだが
Swiftでは以下の通り

| アクセス修飾子       |   説明    |
|:-----------------|:------------------|
| open             |どこからでもアクセス可能        |
| public           | アクセスはどこからでも可能だがopenと違い別モジュールからの継承とオーバーライドが不可    |
| internal             | モジュール内からのみアクセス可能       |
| fileprivate               |  同じソースファイル内からのみアクセス可能 |
| private             | 定義されているスコープの範囲に限りアクセス可能  |

## クラス
C#と同じ

```swift:class.swift
class GameConsole {}
```

### 継承
C#同様。（多重継承も不可）
親クラスには `super` でアクセス可能

```swift:subclass.swift
class GameConsole {}
class DreamCast : GameConsole {}
```

### オーバーライド
`func`の前に`override`とつけるだけでOK

```swift:override.swift
class GameConsole 
{
	func Execute() { /* 実行処理 */}
}
class DreamCast : GameConsole
{
	override func Execute()
	{
		super.Execute();
	}
}
```

## 構造体
C#と同じで構造体とクラスの違いは値型か参照型の違い
書き方もC#と同様

```swift:struct.swift
struct Gamesoft {}
```

## 列挙型
`enum { case 列挙名 = 列挙するデータ }`と宣言する
またC#等と違い関数を定義することが可能
型名を省略した際はrawValue等で中身が取り出せないため、if,switch等での条件分岐用…？

```swift:enum.swift
enum Encode : String //Stringと型を明示的に指定することでStringも使用可能
{
	case UTF8 = "UTF-8"
	case ShiftJIS = "Shift-JIS"
	case EUC = "EUC-JP"
}

enum Numeric : Int //Intと使用しない場合はrawValueで中身を取り出せない（指定しない場合は中身がそもそも存在しない？？）
{
	case Zero, One, Two, Three
}

print(Encode.UTF8.rawValue) // -> UTF-8
print(Numeric.Zero.rawValue) // -> 0

var jp_default_encode: Encode = .ShiftJIS // 型を明示した場合 .列挙名 という風に書くことが可能
print(jp_default_encode.rawValue) // -> Shift-JIS
```

## Protocol (インターフェース)
C#やJavaでいうところの`interface`
書き方はさほど変わらない。C#と同じでprotocolは同じprotocolであれば複数継承することが可能

```swift:protocol.swift
protocol UserType {}
```

## 拡張メソッド
C#お馴染みの拡張メソッド
Swiftにもあって一安心(拡張メソッド依存者)

宣言方法は `exntension [extension対象クラス] {}`

```swift:extension.swift
extension String
{
	func ToInt() -> Int
	{
		let result = Int(self)
		return result!
	}
}
print("10".ToInt()) // -> 10
```

## 文字列フォーマット
C#では6.0以前では文字列のフォーマットに `string.Format()`を
C#6.0以降からは`$"{}"`が使われてて`$"{}"`こいつが凄い便利だが、Swiftにも似たようなものがあり、下記のように書く
`"\(変数)"`

```swift:format.swift
let name: String = "山田"
let age: Int = 18

print("\(name)は\(age)歳だ") // -> 山田は18歳だ
```

## エイリアス
別名を付ける
C#で言う`using Reader = System.IO.StreamReader`みたいな物

```swift:alias.swift
typealias Name = String
let name: Name = "AziO"
```

## コレクション
### 配列 (Array)
C#で言う`string[] str`のようなもの
`append`関数を使用してデータを追加する

```swift:array.swift
var numberArray = [1, 2, 3, 4, 5]

numberArray[2] *= -1

for i in numberArray
{
	print(i) // 1, 2, -3, 4, 5
}

var emptyArray: [String] = []
emptyArray.append("Hello")
emptyArray.append("Swift")

for i in emptyArray
{
	print(i) // Hello , Swift
}
```

### 辞書 (Dictionary)
C#で言う`Dictionary<T, T2>`

```swift:dictionary.swift
let test = ["山田太郎": 60, "山田花子": 75, "鈴木一郎": 30]

for i in test
{
	print("\(i.key) = \(i.value)")
	// ->
	/*
	山田太郎 = 60
	鈴木一郎 = 30
	山田花子 = 75
	*/
}

var emptyDictionary: [String: Int] = [:]
emptyDictionary["出木杉英才"] = 100

for i in emptyDictionary
{
	print("\(i.key) = \(i.value)") // -> 出木杉英才 = 100
}
```

### タプル (Tuple)
C#でも昔からあったが使いにくく、C#7でSwiftと似たような構文が使えるようになったやつ

```swift:tuple.swift
let jp_country = ("Japan", "円", "東京")
let jp_country2 = (name: "Japan", currency: "円", capital: "東京")

print(jp_country.0) // -> Japan
print(jp_country2.currency) // -> 円
print(jp_country.2) // -> 東京

func ReturnCountry(_ Name: String, _ Currency: String, _ Capital: String)
-> (name: String, currency: String, capital: String)
{
	return (Name, Currency, Capital)
}

print(ReturnCountry("USA", "$", "Washington, D.C.")) // -> (name: "USA", currency: "$", capital: "Washington, D.C.")
```

## ループ

### forループ
現行バージョンSwift3系ではC言語などである`for var i = 0; i < 100; i++`といった構文が使用できなった…らしい（？）
代わりにfor-in Loop形式で対応しましょう

```swift:for.swift
for i in 1...10
{
	print(i) // -> 1 ~ 10
}

let loop_cnt = 5
for i in 1...loop_cnt
{
	print(i) // -> 1 ~ 5
}

for i in 1..<loop_cnt
{
	print(i) // -> 1 ~ 4
}
```

### while ループ
C#で言うwhileはほぼ同じ書き方`while 条件式 { ～ }`
do-whileは`repeat { ～ } while 条件式`と書く

```swift:while.swift
var i = 0
while case 0...10 = i
{
	print(i) // -> 0 ~ 10
	i += 1
}
```

### foreachは？
C#で言うforeachはfor-in Loopに組み込まれているのでそちらを使いましょう
C#の`List`に実装されている`ForEach(Action)`に似たものならあります

```swift:foreach.swift
Array(0...100).forEach {print("\($0)")} // -> 0 ~ 100 $0はクロージャ引数で $0,1,2,3と順に振られていくらしい
```

# LINQは？？？
C#と言えばLINQというイメージ、むしろLINQがあったからC#を使ってるといっても過言ではない私ですが
LINQっぽい物はあるようです
下のサンプルはどんな仕組みで動いてるのかさっぱりなので正しいコードかどうかはかなり微妙です（動作はします）

```swift:LINQ.swift
//テストの結果を用意し50点以上を取った人の名前を取得
let test = ["山田太郎": 60, "山田花子": 75, "鈴木一郎": 30]

let score = test.filter { $0.value >= 50}.map { $0.key }

for i in score
{
	print(i) // -> 山田太郎 , 山田花子
}

let average = Double( test.map{ $0.value}.reduce(0){ $0 + $1 } ) / Double(test.count)
print(average) // -> 55.0
```

# まとめた感想
**「あれ？Swift割と良さげじゃね…？」**
C#にどっぷりつかっていた身としては気になる点はいくつかありますがおおむね高評価です

気になる点リスト（こんなんあるよ、それはちがうよあればお気軽にコメント等どうぞ）

- LINQっぽい機能（なんていう正式名称なんでしょうかあれ…）がLINQに比べて貧弱な気がする
    - @loveeさん提供 : flatMapを使用すればLINQでできることは大体できる模様
- プロパティの自動実装 `string Name {get; set;}`みたいなの無いとちょっと不便
    - C#/Java程プロパティは乱用しないようです
- C#と比べてパフォーマンスはどれぐらい出るんだろう？（実機が無いので検証が出来ない）
- Objective-C時代は参照カウンタに悩まされた経験があるけどSwiftはGCとかそこらへんどうなってるんだろう
    - @takabosoft さん提供 : 現在はARCと言ったスマートポインタのようなものがあるため昔ほど気にならなくなった

もっといろいろ判明したら Part2 とか上げてみたいと思います

# 参考にしたサイト様
とても参考になりました、ありがとうございます

- [Swift3.0を学ぶにあたって知っておきたい基礎文法（前編）](http://dev.classmethod.jp/smartphone/iphone/swift3_code_tutorial1/)
- [Swift3.0を学ぶにあたって知っておきたい基礎文法（後編）](http://dev.classmethod.jp/smartphone/iphone/swift3_code_tutorial2/)
- [SwiftのArrayとDictionaryの使い方](http://qiita.com/hachinobu/items/d591d0cba23b6dfec559)
- [Swiftのクラスと構造体の使い分けについてのメモ](http://qiita.com/mini_house/items/22b7b88794b9f8a32381)
- [Swiftのタプルと引数･戻り値](http://qiita.com/tottokotkd/items/7b51dd211dcce1e4e55b)
- [Swift言語を学ぶ](http://tea-leaves.jp/swift/)
- [Swiftを書く時に気をつける小さな違い](http://qiita.com/kitasuke/items/3cc194542ee45a92bef2)
- [Swiftの「エクステンション」と「プロトコル」～ 機能と役割、Objective-Cとの違いを知る](https://codezine.jp/article/detail/8293)