30
C# Design Note 岩岩 岩岩 ++C++; // 未未未未未 C

C# design note sep 2014

  • Upload
    -

  • View
    9.913

  • Download
    1

Embed Size (px)

DESCRIPTION

2014/9/29 codeseek & C#UG にて

Citation preview

Page 1: C# design note sep 2014

C# Design Note

岩永 信之

++C++; // 未確認飛行 C

Page 2: C# design note sep 2014

Roslyn

• http://roslyn.codeplex.com/• C#/VB コンパイラー再設計プロジェクト• 製品名は「 .NET Compiler Platform 」になりそ

う• いいこと

• MS の中の人が Visual Studio を作りやすくなる• サードパーティ製 VS プラグインが作りやすくなる

• これが一番の急務• おまけで、 C# 言語新機能も足しやすく

Page 3: C# design note sep 2014

今日の話題

• 新機能がどうというより、開発体制の変化• これまで• 製品版の 2 年は前には CTP 提供

• 動くコンパイラー提供• この時点で仕様書結構かっちり / 全機能分

• 今• Roslyn プロジェクトのオープン化

• 最新機能を試したかったら clone して自分でビルド• 緩い段階で仕様公開&ディスカッション / 個別に機能追

Page 4: C# design note sep 2014

Discussions

• Discussions under C# Language Design†• C# の言語機能についてのディスカッション ペー

ジ• 誰でも投稿可能

† http://roslyn.codeplex.com/discussions/topics/5998/c-language-design

Page 5: C# design note sep 2014

Design Notes

• C# Language Design Notes†• C# チームのデザイン ミーティング議事録※

• C# 新機能、案を採用するか否か、実装の方針、懸念点など

※ ディスカッションとして投稿してて、誰でもコメント付け可能

† https://roslyn.codeplex.com/wikipage?title=CSharp%20Language%20Design%20Notes

Page 6: C# design note sep 2014

例えば、 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 公開 ) で実装され

てる

Page 7: C# design note sep 2014

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);拡大

メンバー名を文字列化

Page 8: C# design note sep 2014

#pragma warning extensions• サードパーティ製診断ツールの warning 抑止• 今まで :

コンパイラー正規の警告を警告番号を指定して抑止

Page 9: C# design note sep 2014

#pragma warning extensions• サードパーティ製診断ツールの warning 抑止• 追加 :

(Roslyn を使って作った )VS 拡張による警告を識別子名を使って抑止

Page 10: C# design note sep 2014

この辺りは即断即決

• nameof も #pragma 拡張も、割と手早く仕様が決まって、問題なく実装されてる類

• 悩ましいものも• Design Notes 8/27: parameterless

constructors• Design Notes 9/3: declaration expressions

Page 11: C# design note sep 2014

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

Page 12: C# design note sep 2014

背景 : 既定値

• 値型の既定値は 0 クリアvar points = new Point[1000];

• Point が構造体のとき、コンストラクターを 1000 回呼ぶのか

• 呼びたくないので、 memset(0) にしたい

Page 13: C# design note sep 2014

背景 : new T()

• 現状、 new T() で既定値を作る

• 構造体はパラメーターなしのコンストラクターを持てない

var p = new Point(); 0 クリア

Page 14: C# design note sep 2014

背景 : default(T)

• .NET 2.0 以降には、既定値用の default(T) がある

• ちなみに• .NET IL 仕様上は構造体がパラメーターなしのコン

ストラクター持てる• C# のコンパイラー レベルでエラーにしてる

var p = default(Point); 0 クリア

var p = new Point(); これで 0 クリアする必要まだある?コンストラクター呼んでもよくない?

Page 15: C# design note sep 2014

問題 : generics の new T() 制約• new T() == default(T) 前提の最適化

• new T() がコンストラクターを呼ぶようにするにはここも仕様変更に

T M<T>() where T : new(){ return new T();}

T が構造体の時、 0 クリアに最適化してしまう

Page 16: C# design note sep 2014

問題 : 既定の引数

• 既定の引数 = 定数のみ指定できる

void M(S s = new S()){}

• 現仕様 (new S() == default(S)) なら問題なく使える

• 新仕様 (new S() はコンストラクター呼び出し ) だとダメ

void M(S s = default(S)){}

変更必要

Page 17: C# design note sep 2014

問題 : T(…) : this()

• コンストラクターから引数なしのコンストラクターを呼ぶ場合struct S{ S(int x) : this() { X = x; }

int X { get; set; }}

• 引数なしコンストラクターを定義してある場合、どうなる?

• 0 クリアだけにしたい場合どうする?

S(int x) : default() { X = x; }

別構文が必要かも

Page 18: C# design note sep 2014

検討 : フィールド初期化子

• 引数なしコンストラクターに伴って、構造体でもフィールド初期化子が使えるようにstruct S{ string label = "<unknown>"; bool pending = true;}

構造体でもこういう書き方が可能に

Page 19: C# design note sep 2014

検討 : フィールド初期化子

• 引数なしコンストラクターに伴って、構造体でもフィールド初期化子が使えるように

ただし…• クラスに合わせて引数なしコンストラクターを自

動生成する?• 今の構造体の仕様への追加になるように、引数な

しのコンストラクターを明示的に書かないと初期化子動かなくする?• プライマリー コンストラクターがあるときはどう

する?

Page 20: C# design note sep 2014

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

Page 21: C# design note sep 2014

背景

• 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);

Page 22: C# design note sep 2014

検討 : 宣言した変数のスコープ• 現仕様• 宣言後、ブロックの終わりまで

• 検討事項• ステートメント内に限るべきではないか• 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 使えない

Page 23: C# design note sep 2014

検討 : ステートメント内に限る•ほんとうにステートメントの外で使う?

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 のスコープ広げる?• ステートメント内に限った方がよくない?

Page 24: C# design note sep 2014

検討 : 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句にスコープが漏れるとむしろ使いにくい

Page 25: C# design note sep 2014

検討 : if-else

• else句で使いたい?• else句に変数が残らないようにした場合の問題

• if-else で 1 つのステートメント→ 「変数のスコープはステートメント内で完結」ってシンプルなルールじゃなくなる ( それより短い )

• if (b) S1 else S2とif (!b) S2 else S1で意味が変わる

Page 26: C# design note sep 2014

Pattern Matching

• Draft spec for records and pattern-matching in C#†• C# にも型のパターン マッチングが入りそう• 現在は draft• 実装もあり ( まだ master ブランチには入ってな

い )

† http://roslyn.codeplex.com/discussions/560339

Page 27: C# design note sep 2014

パターン マッチング式

• 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);}

Page 28: C# design note sep 2014

operator is

• 型判定+ is演算子に展開

static bool operator is(Cartesian c, out double x, out double y){ x = c.X; y = c.Y; return true;}

Page 29: C# design note sep 2014

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() { … }}

Page 30: C# design note sep 2014

まとめ

• http://roslyn.codeplex.com/• 開発体制の変化 : オープン化• 最新機能を試したかったら clone して自分でビル

ド• 緩い段階で仕様公開&ディスカッション / 個別に

機能追加

• 最近のディスカッション・仕様追加• 構造体の引数なしコンストラクター• 宣言式の変数スコープ• 型パターン マッチング