Upload
-
View
9.913
Download
1
Embed Size (px)
DESCRIPTION
2014/9/29 codeseek & C#UG にて
Citation preview
C# Design Note
岩永 信之
++C++; // 未確認飛行 C
Roslyn
• http://roslyn.codeplex.com/• C#/VB コンパイラー再設計プロジェクト• 製品名は「 .NET Compiler Platform 」になりそ
う• いいこと
• MS の中の人が Visual Studio を作りやすくなる• サードパーティ製 VS プラグインが作りやすくなる
• これが一番の急務• おまけで、 C# 言語新機能も足しやすく
今日の話題
• 新機能がどうというより、開発体制の変化• これまで• 製品版の 2 年は前には CTP 提供
• 動くコンパイラー提供• この時点で仕様書結構かっちり / 全機能分
• 今• Roslyn プロジェクトのオープン化
• 最新機能を試したかったら clone して自分でビルド• 緩い段階で仕様公開&ディスカッション / 個別に機能追
加
Discussions
• Discussions under C# Language Design†• C# の言語機能についてのディスカッション ペー
ジ• 誰でも投稿可能
† http://roslyn.codeplex.com/discussions/topics/5998/c-language-design
Design Notes
• C# Language Design Notes†• C# チームのデザイン ミーティング議事録※
• C# 新機能、案を採用するか否か、実装の方針、懸念点など
※ ディスカッションとして投稿してて、誰でもコメント付け可能
† https://roslyn.codeplex.com/wikipage?title=CSharp%20Language%20Design%20Notes
例えば、 VS “14” CTP 3 新機能• 7/9 の Agenda†
1. Detailed design of nameof <details settled> 2. Design of #pragma warning extensions <allow
identifiers>
† https://roslyn.codeplex.com/discussions/552377
7/9 の Design Notes の内容がそのまま CTP 3(8/18 公開 ) で実装され
てる
nameof
• メンバー名を文字列化• rename リファクタリングできる string リテラル
class Point(double x, double y) : BindableBase{ double _x = x; double _y = y; public double X { get { return _x; } set { SetProperty(ref _x, value); OnPropertyChanged(nameof(Length)); } } public double Y { get { return _y; } set { SetProperty(ref _y, value); OnPropertyChanged(nameof(Length)); } } public double Length => Math.Sqrt(X * X + Y * Y);}
… 前略… SetProperty(ref _y, value); OnPropertyChanged(nameof(Length)); }} public double Length => Math.Sqrt(X * X + Y * Y);拡大
メンバー名を文字列化
#pragma warning extensions• サードパーティ製診断ツールの warning 抑止• 今まで :
コンパイラー正規の警告を警告番号を指定して抑止
#pragma warning extensions• サードパーティ製診断ツールの warning 抑止• 追加 :
(Roslyn を使って作った )VS 拡張による警告を識別子名を使って抑止
この辺りは即断即決
• nameof も #pragma 拡張も、割と手早く仕様が決まって、問題なく実装されてる類
• 悩ましいものも• Design Notes 8/27: parameterless
constructors• Design Notes 9/3: declaration expressions
Parameterless Constructors• Design Notes 8/27†• The meeting focused on rounding out the
feature set around structs.1. Allowing parameterless constructors in structs
<allow, but some unresolved details> 2. Definite assignment for imported structs <revert
to Dev12 behavior>
† https://roslyn.codeplex.com/discussions/562559
背景 : 既定値
• 値型の既定値は 0 クリアvar points = new Point[1000];
• Point が構造体のとき、コンストラクターを 1000 回呼ぶのか
• 呼びたくないので、 memset(0) にしたい
背景 : new T()
• 現状、 new T() で既定値を作る
• 構造体はパラメーターなしのコンストラクターを持てない
var p = new Point(); 0 クリア
背景 : default(T)
• .NET 2.0 以降には、既定値用の default(T) がある
• ちなみに• .NET IL 仕様上は構造体がパラメーターなしのコン
ストラクター持てる• C# のコンパイラー レベルでエラーにしてる
var p = default(Point); 0 クリア
var p = new Point(); これで 0 クリアする必要まだある?コンストラクター呼んでもよくない?
問題 : generics の new T() 制約• new T() == default(T) 前提の最適化
• new T() がコンストラクターを呼ぶようにするにはここも仕様変更に
T M<T>() where T : new(){ return new T();}
T が構造体の時、 0 クリアに最適化してしまう
問題 : 既定の引数
• 既定の引数 = 定数のみ指定できる
void M(S s = new S()){}
• 現仕様 (new S() == default(S)) なら問題なく使える
• 新仕様 (new S() はコンストラクター呼び出し ) だとダメ
void M(S s = default(S)){}
変更必要
問題 : T(…) : this()
• コンストラクターから引数なしのコンストラクターを呼ぶ場合struct S{ S(int x) : this() { X = x; }
int X { get; set; }}
• 引数なしコンストラクターを定義してある場合、どうなる?
• 0 クリアだけにしたい場合どうする?
S(int x) : default() { X = x; }
別構文が必要かも
検討 : フィールド初期化子
• 引数なしコンストラクターに伴って、構造体でもフィールド初期化子が使えるようにstruct S{ string label = "<unknown>"; bool pending = true;}
構造体でもこういう書き方が可能に
検討 : フィールド初期化子
• 引数なしコンストラクターに伴って、構造体でもフィールド初期化子が使えるように
ただし…• クラスに合わせて引数なしコンストラクターを自
動生成する?• 今の構造体の仕様への追加になるように、引数な
しのコンストラクターを明示的に書かないと初期化子動かなくする?• プライマリー コンストラクターがあるときはどう
する?
Declaration Expressions
• Design Notes 9/3†• The meeting focused on rounding out the
design of declaration expressions1. Removing “spill out” from declaration
expressions in simple statements <yes, remove>
2. Same name declared in subsequent else-if’s <condition decls out of scope in else-branch>
3. Add semicolon expressions <not in this version> 4. Make variables in declaration expressions
readonly <no>
† http://roslyn.codeplex.com/discussions/565640
背景
• declaration expressions 自体は CTP 2 で入ってる• 式の途中で変数宣言
• 問題は、この変数 x のスコープがどこまで続くか
var n = int.TryParse(s, out var x) ? x : 0;
if ((var x = obj as C) != null) { }else { }
var y = (var x = GetValue()) * x;
p.GetCoordinates(out var x, out var y);
検討 : 宣言した変数のスコープ• 現仕様• 宣言後、ブロックの終わりまで
• 検討事項• ステートメント内に限るべきではないか• if-else の場合、 else句ではどうするか
{ var p = new Point(); p.GetCoordinates(out var x, out var y); var p = x * y; // OK Console.WriteLine("{0} = {1} × {2}", p, x, y);}// ここから先、 x, y 使えない
検討 : ステートメント内に限る•ほんとうにステートメントの外で使う?
var n = int.TryParse(s, out var x) ? x : 0;
var y = (var x = GetValue()) * x;
p.GetCoordinates(out var x, out var y);var p = x * y;Console.WriteLine("{0} = {1} × {2}", p, x, y);
x を使いたい範囲
ステートメント内
ステートメント内
こいつ、要る?
• C# だと、多値戻り値自体あまり推奨されてない
• = 利用場面少ない• = レア ケースのために x のスコープ広げる?• ステートメント内に限った方がよくない?
検討 : if-else
• else句で使いたい?• →使いたい方がレア ケース
if (int.TryParse(s, out var x)) { }
if ((var x = obj as A) != null) { }else if ((var x = obj as B) != null) { }else { }
else句で意味ある値持ってない
else句にスコープが漏れるとむしろ使いにくい
検討 : if-else
• else句で使いたい?• else句に変数が残らないようにした場合の問題
• if-else で 1 つのステートメント→ 「変数のスコープはステートメント内で完結」ってシンプルなルールじゃなくなる ( それより短い )
• if (b) S1 else S2とif (!b) S2 else S1で意味が変わる
Pattern Matching
• Draft spec for records and pattern-matching in C#†• C# にも型のパターン マッチングが入りそう• 現在は draft• 実装もあり ( まだ master ブランチには入ってな
い )
† http://roslyn.codeplex.com/discussions/560339
パターン マッチング式
• is を拡張
• switch も拡張if (exp is Add(Expression left, Expression right) { … }
switch (exp){ case Add(Const(0), var x): return x; case Mul(Const(0), var x): return Const(0);}
operator is
• 型判定+ is演算子に展開
static bool operator is(Cartesian c, out double x, out double y){ x = c.X; y = c.Y; return true;}
record 型
• is, Equals, GetHashCode, ToString の自動生成• プライマリ コンストラクターの引数から
プロパティを自動生成record class Point(int X, int Y) { }
class Point(int x, int y){ public int X { get; } = x; public int Y { get; } = y; public static bool operator is(…) { … } override public bool Equals(object obj) { … } override public int GetHashCode() { … } override public string ToString() { … }}
まとめ
• http://roslyn.codeplex.com/• 開発体制の変化 : オープン化• 最新機能を試したかったら clone して自分でビル
ド• 緩い段階で仕様公開&ディスカッション / 個別に
機能追加
• 最近のディスカッション・仕様追加• 構造体の引数なしコンストラクター• 宣言式の変数スコープ• 型パターン マッチング