PowerPoint

C#
C#らしくC#を書こう
自己紹介

岩永 信之

ぐぐれ
このサイトの中の人
テーマ


「C#らしいコードの書き方」というテーマを頼まれています
その前にアンケート

経歴





プログラミング自体経験が浅い人?
C++? Java?
Flash/ActionScript? LAMP系、LLな人?
開発系じゃないけども聞きに来た?
今



Unity? ASP.NET?
その他 C#?
今C#使ってるわけじゃないけど聞きに来た?
C#らしい?

C#だからというわけじゃないけども


他の言語から移ってきた人が戸惑うところ



ソースコード/ライブラリ/アプリの依存関係
イベント
LINQ
Visual Studioに頼ったコーディング



リファクタリング
クラスやメソッドの生成
テスト自動化
前振り: コードの依存関係
依存関係は一方通行に
特定のフレームワークへの依存は少なく
依存関係(1)

基本: 依存は少ないに越したことはない
依存グラフ
どっちがいい?
依存関係(2)

基本: 循環依存はダメ
class A
{
B _b;
}

class B
{
A _a;
}
特に、ライブラリをまたいだ循環依存はダメ
ライブラリX
ライブラリY
class A
{
B _b;
}
class B
{
A _a;
}
依存関係(3)

基本: 画面用フレームワークへの依存は極力避ける
循環、ダメ!
ゲーム画面
GameModel
ゲームの中核処理
Unityなどの
フレームワーク
ASP.NET, Silverlight
などでも同様
画面用フレームワーク
への依存、ダメ!
依存関係を切りたい理由

移植性



違うフレームワークを対象にしたい
サーバーとクライアントで同じコードを共有したい
テストしやすさ


依存関係が複雑になるほどテストが大変
いわゆるprintfデバッグ、ステップ実行デバッグするならコンソール ア
プリが一番
事例: 部分的に流用

全部は要らない
例えば山ほどソース
コードがあったとして
そのうち使いクラスは
1つだけだとして
これだけコピーして
動くかどうか

依存性 = 付随して、何ファイルのコピーが必要になるか
事例: サーバーとクライアントで同じ処理

サーバーとクライアントで同じ処理をしたいことが

例: 毎秒のように更新したいもの


資源の増加量計算
施設建設の完了判定
毎秒問い合わせるのも
コネクションの無駄遣い
クライアント
同じ処理を再実装
サーバー
チート対策もあるので、
クライアント側任せにも
できない
同じ処理は同じコードで

書ければいいけども…

サーバーとクライアントで言語が違う!
クライアント
Flash/ActionScript,
HTML5/JavaScript‡

サーバー
違う
PHP, Python, Perl,
Ruby, Java†
でも、C#ならば
クライアント
Unity/C#,
Silverlight/C#
サーバー
同じ
ASP.NET/C#
†クライアントがAndroidならJava使えるけども
‡サーバー側にNode.js使う?
コード共有するなら

特定のフレームワークに依存しない書き方を
クライアント
(Unityとか)
中核処理
UnityにもASP.NETにも
依存したくない
サーバー
(ASP.NET)
Unityに依存
• UnityEngine名前空間
Silverlightに依存
• System.Windows名前空間
ASP.NETに依存
• System.Web名前空間
この辺りの名前空間のクラス
は、中核処理では使わない
というか、コード共有するなら

特定のフレームワークに依存しない書き方を
こいつも
クライアント
(Unityとか)
サーバー
(ASP.NET)
こいつもデバッグ
実行遅くない?
中核処理
コンソール アプリ
単体テスト
こっちでデバッグするのが低ストレス
依存切り
依存関係を一方通行にする
特定のフレームワークへの依存をなくす
依存を最小限にしたいフレームワーク

GUI


ウェブがらみ


Unity、 Silverlight、 ASP.NET(HTML画面を生成)
ASP.NET(JSON返すだけとかでも)
セキュリティ的に怪しい部分

ファイル読み書きなど
書き込み権限与えていいのか
スマホだと、アプリをまたいだファイル共有認めてない
ブラウザーなんかはそもそもファイルアクセス無理
依存切りの定石1
フレームワーク依存部分に処理を書かない
ビューとかコントローラーとか言われる部分
フレームワーク依存部分に処理を書かない

例えばUnity
画面側コード(この例だとコントローラー)
using UnityEngine;
public class CityController : MonoBehaviour
{
void Update()
{
こういうところにゲームの
}
中核処理を書いちゃダメ
}


Unity依存
コントローラーなら、プレイヤーの入力に応じてモデルを呼ぶだけ
ビューなら、描画などの処理だけ書く
フレームワーク依存部分に処理を書かない

例えばASP.NET MVC
画面側コード(この例だとコントローラー)
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
こういうところにゲームの
}
中核処理を書いちゃダメ
}
}
ASP.NET依存
依存切りの定石2
インターフェイスやデリゲートを利用
インターフェイスやデリゲートを使った依存切り

循環依存をなくすための定石
class A
{
B _b;
}
class B
{
A _a;
}
class A
{
IB _b;
}
class B : IB
{
A _a;
}
interface IB
{
}
一方通行に
C#の場合はデリゲート
(関数ポインターみたいなもの)
を使うことも多い。
インターフェイスやデリゲートを使った依存切り

例: いわゆるprintfデバッグ

Unityの場合、UnityEngine.Debugクラスを利用
中核処理側(Unityに依存したくない)
ログの出力先を
外部から与える
public class Debug
{
public static Action<string> Logger { get; set; }
public static void Write(string message)
{
if (Logger != null) Logger(message);
}
}
画面側(Unityを利用)
Models.Debug.Logger = UnityEngine.Debug.Log;
インターフェイスやデリゲートを使った依存切り

例: いわゆるprintfデバッグ

Unityの場合、UnityEngine.Debugクラスを利用
ちゃんと一方通行
ゲーム画面
ゲームの中核処理
• Models.Debugクラス
Unity
• UnityEngine.Debugクラス
ここに依存関係なし
イベント
他の言語からC#に移ってきた人が戸惑う機能その1
オブザーバー パターンを言語構文としてサポート
イベント(一般用語として)

イベント(処理のきっかけ)が外部からやってくる

例: GUIアプリ
1. イベント登録
GUIフレームワーク
(Silverlightなど)
プレイヤーがボタンを
押したら教えて
2. イベント通知
ボタン、押されたよ
アプリのコード
イベントの例

例: WPFアプリ(C#、デスクトップ向けGUI)
using System;
using System.Windows;
using System.Windows.Controls;
public class Program
{
[STAThread]
static void Main()
イベント登録
ボタンが押された時の処理
{
var button = new Button { Content = "ここを押せ" };
button.Click += (sender, e) => MessageBox.Show("ようこそ");
var win = new Window { Content = button };
var app = new Application();
app.Run(win);
}
}
イベントの例

Flash使ったことある人なら

addEventListener
ボタンが押された時の処理
function myEvent(eventObj:MouseEvent)
{
trace("ボタンがクリックされました。");
}
myButton.addEventListener(MouseEvent.CLICK,myEvent);
イベント登録
C#のイベント構文

イベントの登録口を生成

add/removeEventListener相当のものを作ってくれる機能
C#のイベント構文を使った、イベント登録口の作成
public class CityModel
{
public event Action<Resource> ResourceUpdated;
}
デリゲートの前にeventキーワードを付けるだけ
意味合い的にはこれに近い
private event Action<Resource> _resourceUpdated;
public void AddResourceUpdatedListener(Action<Resource> listener)
{
_resourceUpdated += listener;
}
public void RemoveResourceUpdatedListener(Action<Resource> listener)
{
_resourceUpdated -= listener;
}
登録口
解除口
C#のイベント構文

イベントの登録口を生成

add/removeEventListener相当のものを作ってくれる機能
C#のイベント構文を使った、イベント登録
CityModel _city;
void Start()
登録
{
_city.ResourceUpdated += _city_ResourceUpdated;
}
void _city_ResourceUpdated(Resource obj)
{
// 更新があった時の処理
}
解除は -= で
イベントの使いどころ

受け身に処理したいとき

イベントが起きた時にだけ動きたい
(イベント駆動型プログラム)


普段は何もせず待機
変化が少ない(イベントがあまり起きない)とき、効率的
注意: 2タイプのGUIフレームワーク

ゲーム系



すごく動く上に、パフォーマンスが求められる
フレーム単位で、入力・描画、全部自前で管理
メニュー系


イベント駆動向き
ユーザーが何か操作した時にだけ動く
「ユーザー操作」というイベントを起点にして駆動
ゲームでもメニューよく使うでしょ


カード系ゲームとか、ブラ三的なゲームだと、むしろメニュー系
UIがメイン
一般のゲームでも
例えばRPGでよく見るような画面
C#たん
ステータス
装備
レベル 99
次のレベルまで 0
所持金 1,000,000 G
プレイ時間30:15:00
時間経過で変化
(更新頻度は秒単位)
アイテム
パーティ
プレイ記録
設定
イベント駆動向き
プレイヤーが何か操作す
るまで再描画必要ない
なのでゲームでもイベント駆動

イベント駆動で画面を再描画
モデル側
内政資源、数秒に1回更新する
更新したとき、イベント発行
public class CityModel
{
public event Action<Resource> ResourceUpdated;
}
画面側
void Start()
{
_city.ResourceUpdated += _city_ResourceUpdated;
}
資源の量が変化したときだけ
再描画処理を動かす
LINQ
他の言語からC#に移ってきた人が戸惑う機能その2
データ処理を簡単に
データ処理

例




IDで検索
条件を満たす要素が1つでもあるかどうか探す
合計値や最大値を計算
要はSQLで書くような処理


サーバー側だとデータベース持って、SQL書けばいいけども
データをクライアント側にキャッシュした場合どうする?

メモリ上に読み込んだデータに対してSQL的な処理
LINQ

C#は、SQL的なデータ処理が得意

C# 3.0で導入されたLINQ(Language Integrated Query)
例: 顧客データ一覧から、女性客の年齢分布を求める
var 女性客の年齢分布 =
from c in 顧客一覧
where c.性別 == "女"
group c.年齢 by c.年齢 into g
orderby g.Key
select new { 年齢 = g.Key, 数 = g.Count() };
クエリ式
• SQL的なクエリを書ける
• selectが末尾にくるくらいで、かなりSQLそのまんま
• C#の型をそのまま使える(補完も効く)
LINQ

C#は、SQL的なデータ処理が得意

C# 3.0で導入されたLINQ(Language Integrated Query)
例: 顧客データ一覧から、女性客の年齢分布を求める
var 女性客の年齢分布 = 顧客一覧
.Where(c => c.性別 == "女")
.GroupBy(c => c.年齢, c => c.年齢)
.OrderBy(g => g.Key)
.Select(g => new { 年齢 = g.Key, 数 = g.Count() });
クエリ式の展開結果(メソッドの連鎖になる)
• 元のSQL的な句に対応するメソッドがある
• 使うためには、System.Linq名前空間をusing
データ処理のパーツ

条件選択、グループ化、整列、集計、射影
入力
a
b
c
d
出力
集計
射影
グループ化
整列
集計
射影
where
group by
order by
集計
射影
・・・
from
Aggregate,
Sum, Countなど

だいたいSQLと一緒
select
・・・
・・・
条件選択
α
β
γ
δ
一時リストを作っちゃダメ

例: 偶数だけ選択、二乗を計算
悪い例(一時リストを作成)
var results = new List<int>();
foreach (var x in data)
{
if ((x % 2) == 0)
results.Add(x * x);
}
良い例(LINQ)
var results = data
.Where(x => (x % 2) == 0)
.Select(x => x * x);
サンプル

MSDN公式サンプル: 101 LINQ Samples

http://code.msdn.microsoft.com/101-LINQ-Samples3fb9811b
補足: 匿名関数

その場限りの関数を作れる
var results = data
.Where(x => (x % 2) == 0)
.Select(x => x * x);
こんなんのために、いちいち
// x が偶数のとき true
static bool IsEven(int x)
{
return (x % 2) == 0;
}

=>(goes to)演算子

引数 => 式
こんな感じのメソッド作りたくない
// 二乗を計算
static int Square(int x)
{
return x * x;
}
補足: 拡張メソッド


LINQのSelectなどは、実は「拡張メソッド」
静的メソッドを、後置き記法で書く機能
本来、こう書く必要がある(実は静的メソッド)
var results = Enumerable.Select(data, x => x * x);
拡張メソッドなら
見かけ上、インスタンス メソッド的に書ける(後置き記法にできる)
var results = data.Select(x => x * x);


メソッドを連鎖的に書きやすい
Enumerableなどのクラス名を省略できる
EnumerableクラスはSystem.Linq名前空間にある
補足: 拡張メソッド


LINQのSelectなどは、実は「拡張メソッド」
静的メソッドを、後置き記法で書く機能
拡張メソッドの実装例
public static class Enumerable
{
第1引数にthispublic static IEnumerable<U> Select<T, U>(
this IEnumerable<T> source,
修飾子を付ける
Func<T, U> selector)
{
foreach (var x in source)
{
yield return selector(x);
}
}
}
Visual Studioに頼ろう
ライブ コーディングでも見せようかと
Visual Studio


もちろん、生産性向上のためのツールだけども
学習ツールとしても優秀


まず、Visual Studioの作るテンプレや、補完で出てくるコードを覚
えよう
デモ


コード スニペット
スマート タグ
デモ





foreach
メソッド抽出
usege-first
単体テスト生成
LINQ
サンプル

HTMLスクレイピング


15パズル


http://code.msdn.microsoft.com/C-15Visual-Studio5511658e
http://code.msdn.microsoft.com/C-2-83b48d3f
東方弾幕風もどき