Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
C# 6.0
C# とともに祝15周年
岩永信之
数年待った新仕様
• async/awaitの情報が出始める
• Visual Studio 2012でC# 5.0正式リリース
• C# 6.0の情報が出始める
• C# 7.0の提案が始まる
• Visual Studio 2015でC# ...
Roslyn (潜伏の理由)
• 新コンパイラー(製品名 .NET Compiler Platform)
• 作り直し
• C++コンパイラーの保守がもうつらい
• Visual Studio拡張と、コンパイラー用のコード2重開発がつらい
• ...
.NET 2015とRoslyn
language toolruntime library ecosystem
C# 6.0/VB 14 Ryu JIT
.NET Native
.NET Fx 4.6
.NET Core 5
Visual St...
C# 6.0
• テーマ(?): Just-do-it (いいからやれよ)
• Roslyn化で手いっぱい → 大きなものが入らない
• 潜伏期間が長すぎた。これ以上待たせたくない
• 大きなものはC# 7.0行き
• Roslynにしたからこ...
C# 7.0 (提案開始、ディスカッション中)
• テーマ
• データ
• Null
• パフォーマンスと信頼性
• コンポーネント化
• 分散コンピューティング
• メタプログラミング
https://github.com/dotnet/ro...
本日はC# 6.0の方のみ
• C# 6.0の新機能
• Deep Dive
• 用途・効能(実測)
• 背景・裏話
自動プロパティの改善 式形式の関数メンバー
using static null条件演算子 文字列挿入
nameof 式 インデ...
プロパティやメソッドの改善
• プロパティやメソッドがだいぶ書きやすく
• 式形式の関数メンバー(expression bodied function members)
• メソッド/演算子(expression bodies on metho...
背景: よくあるコード(1)
• 割と単純な計算
class Calculator
{
public double Square(double x) { return x * x; }
}
背景:よくあるコード(2)
• 子オブジェクトに丸投げ
class Sample1 : Sample
{
Sample _inner;
public override string X() { return _inner.X(); }
}
背景:よくあるコード(3)
• readonlyにするためだけにフィールド定義
class Immutable
{
private readonly int _x;
public int X { get { return _x; } }
pub...
背景:よくあるコード(4)
• 初期化するためだけにフィールド定義
class Root
{
private List<string> _items = new List<string>();
public IList<string> Item...
背景: 共通していえること
• { return ; } うざい
• しかも頻出
public double Square(double x) { return x * x; }
public int X { get { return _x; ...
式形式のメソッド/演算子
• returnステートメント1つだけの場合、=> を使って短縮可能
• ラムダ式と同じルール
public override string X() { return _inner.X(); }
public doub...
式形式のプロパティ/インデクサー
• getter-onlyな場合だけ、同様に => を使って短縮可能
• { get { return ; } } を消せる
public int X { get { return _x; } }
public...
自動プロパティ初期化子
• 自動プロパティに対して初期化子が書けるように
• 明示的なフィールド定義が不要に
class Root
{
private List<string> _items = new List<string>();
publ...
getter-onlyな自動プロパティ
• コンストラクター内でだけ初期化できる自動プロパティ
• { get; } だけ書く
class Immutable
{
private readonly int _x;
public int X { ...
没案: プライマリ コンストラクター
• 当初予定では、もう1つ文法が提案されてた
• C# 7.0で、より高度な新機能に統合予定
• プライマリ コンストラクター(没) → レコード型(7.0)
class Immutable(int x)
...
効能
• どのくらいのインパクトがあるか実測
• 計測用のプログラム:
• https://github.com/ufcpp/UfcppSample/tree/master/Scribble/FindSingleStatementBody
• ...
効能: メソッド統計
全体, 16260
0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
式1つだけ, 8343 それ以外, 7917
0% 10% 20% 30% 40% 50% 60% 70% 80%...
効能: プロパティ統計
全体, 5385
0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%getのみ, 2225 自動実装, 1690 1470
0% 10% 20% 30% 40% 50% 60% 70%...
効能: プロパティ統計
全体, 5385
0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%getのみ, 2225 自動実装, 1690 1470
0% 10% 20% 30% 40% 50% 60% 70%...
using static
• 静的メソッドを、メソッド名だけで呼べるように
• using static構文を使う
using System;
public class Program
{
static void Main()
{
Consol...
using staticの用途(1)
• クラスにあまり意味がないもの
• グローバル関数の代わり
• Mathとかが好例
using static System.Math;
class MathSample
{
double F(int x)...
using staticの用途(2)
• ファクトリ メソッド
• 諸事情あってコンストラクターを公開せず、メソッド越しに作るもの
• Expressionとかが好例
using System.Linq.Expressions;
using s...
元々はC#スクリプト用
• Roslynの最終目標には「C#スクリプト」も入っている
• (手が回っていなくて未実装)
• 自作アプリに組み込んでマクロ実行
• REPL上で1行1行C#ステートメントを実行
• スクリプト実行時限定のつもりで機...
静的プロパティ/非静的クラス
• 静的プロパティ可
• 静的クラスである必要ない
using static System.DateTime;
using static System.Console;
public class Program
{...
拡張メソッド
• 拡張メソッドは、静的メソッドとしては呼べない
• 拡張メソッドとしては使える
LINQでおなじみのEnumerableクラス
Enumerable中の拡張メソッド
拡張メソッドを静的メソッドとしては呼べない
staticが付く理由
• もし、staticを付けないと
• 当初提案では付けなくてもよかった
• 結構極悪なコードを書けてやばかったから修正
using System.Linq;
namespace System
{
public stat...
null条件演算子(null conditional operator)
• ?. で nullチェック + メンバー アクセス
• 左辺が null だったら戻り値に null 伝搬
• ?? と組み合わせるのも有効
string name;...
インデクサー/多段チェック
• ?[] でインデクサーに対しても null チェック可能
• 1つの式で多段チェック可能
var m = team.Units?[0]?.Master;
var unit = team.Units != null...
デリゲート/イベント呼び出し
• ?() とは書けない
• 条件演算子 ? : との区別が構文上難しい
• デリゲートなら、?.Invoke で代用可能
void OnPropertyChanged(string propertyName)
=...
用途
• null許容な文脈と、非null許容な文脈ははっきり分かれる
• 許容する方で活躍するはず
例
一覧画面
A B
(順序・位置などに意味があるような)
一覧画面では「空欄」があり得る
空欄をnullで表したり
C
詳細画面
C
wei...
没案: null非許容
• より重要なのは非nullの方
• 現状のC#ではnullを認めないコードを書くのが大変
• C# 7.0で検討中
void ShowDetail(Unit! unit)
{
...
}
(現状の案)
! で非null...
文字列挿入(string interpolation)
• 文字列整形がだいぶ楽に
• $ から文字列を始める
• {} の中に任意の式が書ける
string.Format("({0}, {1})", x, y);
string.Format(...
複数行
• $@ から始める
• ちなみに逆(@$)はダメ(コンパイル エラー)
Console.WriteLine($@"
x: {x}
y: {y}
");
string.Format化
• コンパイル結果
• 要望多かったのに今まで入れなかった理由は単純に
「ライブラリでできることはライブラリでやれ」
• まさに「just-do-it」の代表格
• Roslynになって保守コストが下がったから入れ...
IFormattable
• IFormatProviderを指定したい場合
• (カルチャー指定などをしたい場合)
• stringじゃなくてIFormattableで受ける
• .NET 4.6/.NET Core 5を必要とする唯一の機能...
nameof式(nameof expression)
• 識別子(変数名、メンバー名、クラス名…)を文字列リテラル化
if (x < 0)
throw new ArgumentException("x must be positive");
i...
nameof式(nameof expression)
• 結構複雑な式も書ける
var now = DateTime.Now;
var x1 = nameof(now.AddHours);
var x2 = nameof(IList<int>....
補足: CallerMemberName
• PropertyChanged用途だと、こんな方法も
• ただし、これでは不十分場合あり
private int _x;
public int X
{
get { return _x; }
set ...
補足: CallerMemberNameでは不十分
• パフォーマンス考えるとよりよい書き方があって
public int X
{
get { return _x; }
set { _x = value; PropertyChanged?.In...
補足: CallerMemberNameでは不十分
• 他のプロパティに依存したプロパティ
public int X
{
get { return _x; }
set { _x = value; OnPropertyChanged(); OnP...
インデックス初期化子
• オブジェクト初期化子内にインデクサーを書ける
• 利点
• オブジェクト初期化子で、プロパティと混ぜれる
• 式になる
• => で使える、フィールド初期化子で使える、式ツリー化できる
var d = new Dict...
light weight dynamic
• 裏にあるストーリーは結構壮大
• 場合によっては、辞書的にプロパティ アクセスしたい
• ライブラリ内がリフレクションだらけになったり
{
"Id": 10,
"Position": { "X": ...
light weight dynamic
• プロパティ アクセスと辞書アクセスを近づける発想
var p = new Point();
p.X = 1;
p.Y = 2;
var d = new Dictionary();
d["X"] = ...
Working with data
• C# 7.0の大きなテーマの1つ
• light weight dynamicはそのはしり
• 7.0にご期待ください
• レコード型、タプル型
「データ」が主役
var d = new Dictiona...
例外フィルター
• 例外 catch に条件を付けれるように
• ちなみに
• C#的には新機能だけど、.NET的には1.0のころから持ってる機能
• C#がそれに対応しただけ
try
{
…
}
catch (Exception ex) wh...
用途: inner exceptionでcatch
static void Main()
{
try
{
RunAsync().Wait();
}
catch (InvalidOperationException)
{
Console.Writ...
用途: inner exceptionでcatch
static void Main()
{
try
{
RunAsync().Wait();
}
catch (AggregateException ae)
when (ae.InnerExce...
用途: 複数種の例外
• 複数種類の例外に対して同じ処理
try
{
…
}
catch (Exception ex)
when (ex is AccessViolationException || ex is FileNotFoundExce...
没案: if
• 当初提案ではifキーワードだった
• {} のちょっとした位置で意味が全く変わるとかちょっと
try
{
}
catch (Exception ex) if (ex.InnerException is IOException)...
catch句、finally句でのawait
AsyncResource asyncResource = null;
try
{
asyncResource = new AsyncResource();
}
catch (Exception e...
今までなかったのは
• yield return
• awaitの発想の元になっているのがyield return
(awaitのコード生成結果はyield returnに近い)
• yield returnはtry-catch-finally...
拡張メソッドでコレクション初期化子
• コレクション初期化子の結果として呼ばれるAddメソッドが
拡張メソッドでもOKに
var points = new List<Point>
{
new Point(3, 4),
};
var points...
今までなかったのは
• コンパイル時間を気にしてのことらしい
• 拡張メソッドの検索はノーコストではない
• といっても、普通の拡張メソッドとそんなにコスト変わらないはず
• VBは昔からできてた
まとめ
• Just-do-it
• Roslyn化に時間をかけすぎたのでコンパクトに
• Roslynになったからこそ保守コストが下がって新機能入れやすく
• ロー コスト・ロー リターンな機能ばかりだけど、確実に便利に
• いくつかは、7....
おまけ
• ここから先、時間が残れば
その他小さな変更
• これまでも、大々的に出てない小さな変更はあった
• 特に、破壊的変更
• Visual C# 2008 Breaking Changes
• Visual C# 2010 Breaking Changes
• Visual...
C# 6.0の破壊的変更(1)
• コンストラクターの再帰循環参照
• 昔: 実行時にスタック オーバーフロー
• C# 6.0: コンパイル エラー
class C
{
public C(int x) : this() { }
public ...
C# 6.0の破壊的変更(2)
• generic型インスタンスに対するlock
• 昔: コンパイル通るものの、値型の場合lockの意味ない
• C# 6.0: class制約が必須に
public void DoSomething<T>(T...
C# 6.0の破壊的変更(3)
• generic型の静的readonlyフィールドに対する書き込み
• 昔: 他の特殊化に対して初期化できる
• C# 6.0: 自分自身だけを初期化できる
public static class Foo<T>...
日本人だけが気づく破壊的変更
• Unicodeの変更の影響
• 昔: カタカナ中点(中黒)OK
• C# 6.0: Unicode側のミスでした。Unicodeが修正したらC#にも影響出ま
した
int x・y = 10;
Console.W...
微妙な新機能(1)
• enumの基底型
• 昔: int, short, long など、キーワードでないとダメ
• C# 6.0: Int32, Int16, Int64 など、System名前空間の型でもOK
enum X : Syste...
微妙な新機能(2)
• オーバーロード解決ルールを改善
• 昔: ラムダ式の型推論、1段は行けてたけど2段は無理だった
• C# 6.0: 2段以上もOK
using System;
class FuncOfFuncTypeInference
...
追悼
• 一瞬、C# 6.0に入る予定だったもの
• 互換性壊れるので取りやめたり
• 引数なしの構造体コンストラクター
• C# 7.0で改めて取り組むことになったり
• プライマリ コンストラクター → レコード型
• 変数宣言式 → パタ...
追悼: 構造体の引数なしコンストラク
ター
• 構造体にも引数なしのコンストラクターを定義できるようにす
るはずだった
• .NETのランタイム レベルでバグがあることが発覚して断念
• Activator.CreateInstance<T>(...
追悼: プライマリ コンストラクター
• 型定義の型名の直後にコンストラクターを1個書けた
• 7.0でレコード型に吸収予定
class Immutable(int x)
{
public int X { get; } = x;
}
class...
追悼: 変数宣言式(declaration expressions)
• 式の途中で変数宣言できた
• 7.0でパターン マッチングと合わせて作り直す予定
while ((var line = Console.ReadLine()) != nu...
Nächste SlideShare
Wird geladen in …5
×

Deep Dive C# 6.0

77.301 Aufrufe

Veröffentlicht am

2015/4/11
dotNetConf 2015 Japan with JXUG
https://atnd.org/events/63844
にて登壇。

Veröffentlicht in: Technologie
  • Dating direct: ❤❤❤ http://bit.ly/33tKWiU ❤❤❤
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Sex in your area is here: ❤❤❤ http://bit.ly/33tKWiU ❤❤❤
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • DOWNLOAD THAT BOOKS/FILE INTO AVAILABLE FORMAT - (Unlimited) ......................................................................................................................... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes Christian, Classics, Comics, Contemporary, Cookbooks, Art, Biography, Business, Chick Lit, Children's, Manga, Memoir, Music, Science, Science Fiction, Self Help, History, Horror, Humor And Comedy, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance,
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • DOWNLOAD THAT BOOKS/FILE INTO AVAILABLE FORMAT - (Unlimited) ......................................................................................................................... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes Christian, Classics, Comics, Contemporary, Cookbooks, Art, Biography, Business, Chick Lit, Children's, Manga, Memoir, Music, Science, Science Fiction, Self Help, History, Horror, Humor And Comedy, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance,
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • If you want to download or read this book, Copy link or url below in the New tab ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... .........................................................................................................................
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

Deep Dive C# 6.0

  1. 1. C# 6.0 C# とともに祝15周年 岩永信之
  2. 2. 数年待った新仕様 • async/awaitの情報が出始める • Visual Studio 2012でC# 5.0正式リリース • C# 6.0の情報が出始める • C# 7.0の提案が始まる • Visual Studio 2015でC# 6.0正式リリース 2010 2011 2012 2013 2014 2015 潜伏期 • 裏でRoslynを作ってて、言語的な新機能何もなし 久しぶりに楽しい時期
  3. 3. Roslyn (潜伏の理由) • 新コンパイラー(製品名 .NET Compiler Platform) • 作り直し • C++コンパイラーの保守がもうつらい • Visual Studio拡張と、コンパイラー用のコード2重開発がつらい • C#チームが作っているコンパイラーの力を、Visual Studio拡張を作って いるサードパーティ企業・個人開発者が活用できないのがつらい • C#でC#コンパイラーを、VBでVBコンパイラーを • 単一コンパイラーでコンパイルとVisual Studio拡張を • コンパイラーの内部データをとれるAPI公開
  4. 4. .NET 2015とRoslyn language toolruntime library ecosystem C# 6.0/VB 14 Ryu JIT .NET Native .NET Fx 4.6 .NET Core 5 Visual Studio 2015 NuGet .NET 2015 新しいコンパイラー csc.exe/vb.exe コード解析ライブラリ Microsoft.CodeAnalysis Roslyn それぞれ独立 • C# 6.0で.NET Framework 2.0開発とかも可能 • .NET 4.5以上をインストールすればMicrosoft.CodeAnalysis利用可能 • Visual Studio 2012は最初から.NET 4.5
  5. 5. C# 6.0 • テーマ(?): Just-do-it (いいからやれよ) • Roslyn化で手いっぱい → 大きなものが入らない • 潜伏期間が長すぎた。これ以上待たせたくない • 大きなものはC# 7.0行き • Roslynにしたからこそ → 細々とした機能を保守できる • コンパイラー自身がC#製になったから本気出す • 「よくあるパターン」のめんどくささを改善
  6. 6. C# 7.0 (提案開始、ディスカッション中) • テーマ • データ • Null • パフォーマンスと信頼性 • コンポーネント化 • 分散コンピューティング • メタプログラミング https://github.com/dotnet/roslyn/issues/98 この辺りのテーマはC# 6.0で いくつか簡単なものが入ってる
  7. 7. 本日はC# 6.0の方のみ • C# 6.0の新機能 • Deep Dive • 用途・効能(実測) • 背景・裏話 自動プロパティの改善 式形式の関数メンバー using static null条件演算子 文字列挿入 nameof 式 インデックス初期化子 catch/finally内でawait 拡張メソッドでコレクション初期化子 例外フィルター
  8. 8. プロパティやメソッドの改善 • プロパティやメソッドがだいぶ書きやすく • 式形式の関数メンバー(expression bodied function members) • メソッド/演算子(expression bodies on method-like members) • プロパティ/インデクサー(expression bodies on property-like members) • 自動プロパティの改善(auto-property enhancements) • 自動プロパティ初期化子(auto-property initializers) • getter-onlyな自動プロパティ(getter-only auto-properties)
  9. 9. 背景: よくあるコード(1) • 割と単純な計算 class Calculator { public double Square(double x) { return x * x; } }
  10. 10. 背景:よくあるコード(2) • 子オブジェクトに丸投げ class Sample1 : Sample { Sample _inner; public override string X() { return _inner.X(); } }
  11. 11. 背景:よくあるコード(3) • readonlyにするためだけにフィールド定義 class Immutable { private readonly int _x; public int X { get { return _x; } } public Immutable(int x) { _x = x; } }
  12. 12. 背景:よくあるコード(4) • 初期化するためだけにフィールド定義 class Root { private List<string> _items = new List<string>(); public IList<string> Items { get { return _items; } } }
  13. 13. 背景: 共通していえること • { return ; } うざい • しかも頻出 public double Square(double x) { return x * x; } public int X { get { return _x; } } public IList<string> Items { get { return _items; } } public override string X() { return _inner.X(); } 特にこいつなんて、書きたいもの(_x)に対して ノイズ({ get { return ; } })が多すぎ
  14. 14. 式形式のメソッド/演算子 • returnステートメント1つだけの場合、=> を使って短縮可能 • ラムダ式と同じルール public override string X() { return _inner.X(); } public double Square(double x) { return x * x; } public override string X() => _inner.X(); public double Square(double x) => x * x;
  15. 15. 式形式のプロパティ/インデクサー • getter-onlyな場合だけ、同様に => を使って短縮可能 • { get { return ; } } を消せる public int X { get { return _x; } } public int X => _x;
  16. 16. 自動プロパティ初期化子 • 自動プロパティに対して初期化子が書けるように • 明示的なフィールド定義が不要に class Root { private List<string> _items = new List<string>(); public IList<string> Items { get { return _items; } } } class Root { public IList<string> Items { get; private set; } = new List<string>(); }
  17. 17. getter-onlyな自動プロパティ • コンストラクター内でだけ初期化できる自動プロパティ • { get; } だけ書く class Immutable { private readonly int _x; public int X { get { return _x; } } public Immutable(int x) { _x = x; } } class Immutable { public int X { get; } public Immutable(int x) { X = x; } }
  18. 18. 没案: プライマリ コンストラクター • 当初予定では、もう1つ文法が提案されてた • C# 7.0で、より高度な新機能に統合予定 • プライマリ コンストラクター(没) → レコード型(7.0) class Immutable(int x) { public int X { get; } = x; } class Immutable { public int X { get; } public Immutable(int x) { X = x; } } プライマリ コンストラクター(没) 未
  19. 19. 効能 • どのくらいのインパクトがあるか実測 • 計測用のプログラム: • https://github.com/ufcpp/UfcppSample/tree/master/Scribble/FindSingleStatementBody • せっかくなのでMicrosoft.CodeAnalysisライブラリを利用 • 今仕事で使っているソリューションを1個、集計してみた
  20. 20. 効能: メソッド統計 全体, 16260 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 式1つだけ, 8343 それ以外, 7917 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 全体のうち51.3% が => 化の恩恵を受ける
  21. 21. 効能: プロパティ統計 全体, 5385 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%getのみ, 2225 自動実装, 1690 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%式1つ, 2101 自動実装, 1690 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%243 1858 372 1318 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% フィールドの値を返すだけ private set 全体のうち39% getのみのプロパティの94.4% が => 化の恩恵を受ける
  22. 22. 効能: プロパティ統計 全体, 5385 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%getのみ, 2225 自動実装, 1690 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%式1つ, 2101 自動実装, 1690 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%243 1858 372 1318 1470 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% フィールドの値を返すだけ private set 合計615個(全体の11.4%)※が 自動プロパティの改善の恩恵受ける ※ public setなものの多くがJSON化の都合でpublic。実際には書き替えしてない
  23. 23. using static • 静的メソッドを、メソッド名だけで呼べるように • using static構文を使う using System; public class Program { static void Main() { Console.WriteLine("hello"); } } using static System.Console; public class Program { static void Main() { WriteLine("hello"); } } System.Console.WriteLine が呼ばれる
  24. 24. using staticの用途(1) • クラスにあまり意味がないもの • グローバル関数の代わり • Mathとかが好例 using static System.Math; class MathSample { double F(int x) => x * Log(x); double G(int x) => Sin(x) * Exp(x); } 数学関数ばっかり使うような文脈で、 1個1個 Math. を付けたくない
  25. 25. using staticの用途(2) • ファクトリ メソッド • 諸事情あってコンストラクターを公開せず、メソッド越しに作るもの • Expressionとかが好例 using System.Linq.Expressions; using static System.Linq.Expressions.Expression; class ExpressionSample { static ParameterExpression x = Parameter(typeof(int)); static ParameterExpression y = Parameter(typeof(int)); static Expression ex = Lambda(Add(x, y), x, y); } Expressionクラスの静的メソッドで インスタンス生成
  26. 26. 元々はC#スクリプト用 • Roslynの最終目標には「C#スクリプト」も入っている • (手が回っていなくて未実装) • 自作アプリに組み込んでマクロ実行 • REPL上で1行1行C#ステートメントを実行 • スクリプト実行時限定のつもりで機能を追加した • あまりにも要望多すぎて、通常のC#にも実装
  27. 27. 静的プロパティ/非静的クラス • 静的プロパティ可 • 静的クラスである必要ない using static System.DateTime; using static System.Console; public class Program { public static void Main() { WriteLine(Now); } } 普通の(static が付かない)クラス (こっちは静的クラス) 静的プロパティ
  28. 28. 拡張メソッド • 拡張メソッドは、静的メソッドとしては呼べない • 拡張メソッドとしては使える LINQでおなじみのEnumerableクラス Enumerable中の拡張メソッド 拡張メソッドを静的メソッドとしては呼べない
  29. 29. staticが付く理由 • もし、staticを付けないと • 当初提案では付けなくてもよかった • 結構極悪なコードを書けてやばかったから修正 using System.Linq; namespace System { public static class Linq { public static string nameof(Action x) => ""; } } 既存の名前空間と同名のクラス 元とは別の定義を紛れ込ませられる 没
  30. 30. null条件演算子(null conditional operator) • ?. で nullチェック + メンバー アクセス • 左辺が null だったら戻り値に null 伝搬 • ?? と組み合わせるのも有効 string name; if (unit == null) name = "空欄"; else name = unit.Master.Name; var name = unit?.Master.Name ?? "空欄"; var name = unit == null ? "空欄" : unit.Master.Name; あるいは
  31. 31. インデクサー/多段チェック • ?[] でインデクサーに対しても null チェック可能 • 1つの式で多段チェック可能 var m = team.Units?[0]?.Master; var unit = team.Units != null ? team.Units[0] : null; var m = unit != null ? unit.Master : null;
  32. 32. デリゲート/イベント呼び出し • ?() とは書けない • 条件演算子 ? : との区別が構文上難しい • デリゲートなら、?.Invoke で代用可能 void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  33. 33. 用途 • null許容な文脈と、非null許容な文脈ははっきり分かれる • 許容する方で活躍するはず 例 一覧画面 A B (順序・位置などに意味があるような) 一覧画面では「空欄」があり得る 空欄をnullで表したり C 詳細画面 C weight : 327 dimension: 14.6×14×3.5 詳細画面では無効な項目 の表示は想定しない タップで 画面遷移 null許容(nullable) 非null (non-nullable)
  34. 34. 没案: null非許容 • より重要なのは非nullの方 • 現状のC#ではnullを認めないコードを書くのが大変 • C# 7.0で検討中 void ShowDetail(Unit! unit) { ... } (現状の案) ! で非nullを明示 ※ 既存のC#コードを壊さないように非null 対応するのはかなり大変で妥協が必要 • 古いコードが混在すると100%の非null 保証は無理 • ! を付ける必要あり 未
  35. 35. 文字列挿入(string interpolation) • 文字列整形がだいぶ楽に • $ から文字列を始める • {} の中に任意の式が書ける string.Format("({0}, {1})", x, y); string.Format("数値: {0:n}, 通貨: {0:c}", x); $"({x}, {y})" $"数値: {x:n}, 通貨: {x:c}" 書式設定も使える
  36. 36. 複数行 • $@ から始める • ちなみに逆(@$)はダメ(コンパイル エラー) Console.WriteLine($@" x: {x} y: {y} ");
  37. 37. string.Format化 • コンパイル結果 • 要望多かったのに今まで入れなかった理由は単純に 「ライブラリでできることはライブラリでやれ」 • まさに「just-do-it」の代表格 • Roslynになって保守コストが下がったから入れれた string.Format("({0}, {1})", x, y); $"({x}, {y})" まんま、string.Formatが生成されるだけ
  38. 38. IFormattable • IFormatProviderを指定したい場合 • (カルチャー指定などをしたい場合) • stringじゃなくてIFormattableで受ける • .NET 4.6/.NET Core 5を必要とする唯一の機能 • FormattableStringは新しく追加された型 • (他は、await除けば.NET 2.0で動く) IFormattable f = $"{x:c}, {x:n}"; var s = f.ToString(null, new CultureInfo("en-us")); FormattableString型の インスタンスが作られる カルチャー指定して文字列化
  39. 39. nameof式(nameof expression) • 識別子(変数名、メンバー名、クラス名…)を文字列リテラル化 if (x < 0) throw new ArgumentException("x must be positive"); if (x < 0) throw new ArgumentException(nameof(x) + " must be positive"); リファクタリングの対象にならない リファクタリングの対象になる • 「リネーム」できる • 「定義に移動」できる • 「参照の検索」できる
  40. 40. nameof式(nameof expression) • 結構複雑な式も書ける var now = DateTime.Now; var x1 = nameof(now.AddHours); var x2 = nameof(IList<int>.Count); var x3 = nameof(System.Text.RegularExpressions.Regex); AddHours Count Regex
  41. 41. 補足: CallerMemberName • PropertyChanged用途だと、こんな方法も • ただし、これでは不十分場合あり private int _x; public int X { get { return _x; } set { _x = value; OnPropertyChanged(); } } void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 自動的に"X"の名前が渡る
  42. 42. 補足: CallerMemberNameでは不十分 • パフォーマンス考えるとよりよい書き方があって public int X { get { return _x; } set { _x = value; PropertyChanged?.Invoke(this, XProperty); } } private static readonly PropertyChangedEventArgs XProperty = new PropertyChangedEventArgs(nameof(X)); 同じインスタンスを使いまわす 方がメモリ効率がいい この場合、CallerMemberName では役に立たない
  43. 43. 補足: CallerMemberNameでは不十分 • 他のプロパティに依存したプロパティ public int X { get { return _x; } set { _x = value; OnPropertyChanged(); OnPropertyChanged(nameof(Sum)); } } public int Y { get { return _y; } set { _y = value; OnPropertyChanged(); OnPropertyChanged(nameof(Sum)); } } public int Sum => X + Y; X, Y の一方でも変化したら Sumの値も変化する この場合、CallerMemberName では役に立たない
  44. 44. インデックス初期化子 • オブジェクト初期化子内にインデクサーを書ける • 利点 • オブジェクト初期化子で、プロパティと混ぜれる • 式になる • => で使える、フィールド初期化子で使える、式ツリー化できる var d = new Dictionary<string, int> { ["X"] = 1, ["Y"] = 2, };
  45. 45. light weight dynamic • 裏にあるストーリーは結構壮大 • 場合によっては、辞書的にプロパティ アクセスしたい • ライブラリ内がリフレクションだらけになったり { "Id": 10, "Position": { "X": 1, "Y": 2 } } <TextBox Text="{Binding Id}" /> <TextBox Text="{Binding Position.X}" /> <TextBox Text="{Binding Position.Y}" /> public int X { set { _x = value; OnPropertyChanged(nameof(X)); } } プロパティ名が キーの辞書
  46. 46. light weight dynamic • プロパティ アクセスと辞書アクセスを近づける発想 var p = new Point(); p.X = 1; p.Y = 2; var d = new Dictionary(); d["X"] = 1; d["Y"] = 2; var p = new Point { X = 1, Y = 2, }; var d = new Dictionary { ["X"] = 1, ["Y"] = 2, }; var d = new Dictionary(); d.$X = 1; d.$Y = 2; var d = new Dictionary { $X = 1, $Y = 2, }; 没 没 一瞬、こういう文法が提案されてた (キモいって言うやつ多すぎるからやめた)
  47. 47. Working with data • C# 7.0の大きなテーマの1つ • light weight dynamicはそのはしり • 7.0にご期待ください • レコード型、タプル型 「データ」が主役 var d = new Dictionary { ["X"] = 1, ["Y"] = 2, }; 低コスト、低リスクなこいつだけが6.0に残った
  48. 48. 例外フィルター • 例外 catch に条件を付けれるように • ちなみに • C#的には新機能だけど、.NET的には1.0のころから持ってる機能 • C#がそれに対応しただけ try { … } catch (Exception ex) when (ex.InnerException is IOException) { … }
  49. 49. 用途: inner exceptionでcatch static void Main() { try { RunAsync().Wait(); } catch (InvalidOperationException) { Console.WriteLine("ここを通ってほしい"); } } static async Task RunAsync() { await Task.Delay(1); throw new InvalidOperationException(""); } 実際にここに来るのは AggregateException もちろんcatchできない
  50. 50. 用途: inner exceptionでcatch static void Main() { try { RunAsync().Wait(); } catch (AggregateException ae) when (ae.InnerExceptions.Any(e => e is InvalidOperationException)) { Console.WriteLine("ここを通ってほしい"); } }
  51. 51. 用途: 複数種の例外 • 複数種類の例外に対して同じ処理 try { … } catch (Exception ex) when (ex is AccessViolationException || ex is FileNotFoundException) { … }
  52. 52. 没案: if • 当初提案ではifキーワードだった • {} のちょっとした位置で意味が全く変わるとかちょっと try { } catch (Exception ex) if (ex.InnerException is IOException) { … } try { } catch (Exception ex) { if (ex.InnerException is IOException) … } 没
  53. 53. catch句、finally句でのawait AsyncResource asyncResource = null; try { asyncResource = new AsyncResource(); } catch (Exception ex) { using (var w = new StreamWriter("log.txt")) await w.WriteAsync(ex.ToString()); throw; } finally { if (asyncResource != null) await asyncResource.DisposeAsync(); } catch句内でawait 用途: • ログ記録 (ファイル書き込みにしろ サーバーに送るにしろ非同期) finally句内でawait 用途: • 非同期Dispose
  54. 54. 今までなかったのは • yield return • awaitの発想の元になっているのがyield return (awaitのコード生成結果はyield returnに近い) • yield returnはtry-catch-finally句内に書けない • 生成されるコードが結構複雑 • 一度すべての例外をcatch→await→再throw的なコードに展開される • catch前のスタックトレースを保ったまま再throwする
  55. 55. 拡張メソッドでコレクション初期化子 • コレクション初期化子の結果として呼ばれるAddメソッドが 拡張メソッドでもOKに var points = new List<Point> { new Point(3, 4), }; var points = new List<Point>(); points.Add(new Point(3, 4)); var points = new List<Point> { { 3, 4 }, }; var points = new List<Point>(); points.Add(3, 4); static class PointExtensions { public static void Add( this IList<Point> list, int x, int y) => list.Add(new Point(x, y)); }
  56. 56. 今までなかったのは • コンパイル時間を気にしてのことらしい • 拡張メソッドの検索はノーコストではない • といっても、普通の拡張メソッドとそんなにコスト変わらないはず • VBは昔からできてた
  57. 57. まとめ • Just-do-it • Roslyn化に時間をかけすぎたのでコンパクトに • Roslynになったからこそ保守コストが下がって新機能入れやすく • ロー コスト・ロー リターンな機能ばかりだけど、確実に便利に • いくつかは、7.0の大きなテーマにつながる機能 • データ: • null: null条件演算子 インデックス初期化子 拡張メソッドでコレクション初期化子
  58. 58. おまけ • ここから先、時間が残れば
  59. 59. その他小さな変更 • これまでも、大々的に出てない小さな変更はあった • 特に、破壊的変更 • Visual C# 2008 Breaking Changes • Visual C# 2010 Breaking Changes • Visual C# Breaking Changes in Visual Studio 2012 • だいたいは以下の類 • 新機能の余波でオーバーロード解決順序変わりました • バグだったのでなおしました • Roslynオープンソース化で、こういう小さな変更も見えやすく なった
  60. 60. C# 6.0の破壊的変更(1) • コンストラクターの再帰循環参照 • 昔: 実行時にスタック オーバーフロー • C# 6.0: コンパイル エラー class C { public C(int x) : this() { } public C() : this(0) { } }
  61. 61. C# 6.0の破壊的変更(2) • generic型インスタンスに対するlock • 昔: コンパイル通るものの、値型の場合lockの意味ない • C# 6.0: class制約が必須に public void DoSomething<T>(T data) { lock (data) { } // << Generates CS0185 } public void DoSomethingElse(SOptions data) { lock (data) { } // << Works fine } public void DoSomething<T>(T data) where T : class { lock (data) { } // Works fine }
  62. 62. C# 6.0の破壊的変更(3) • generic型の静的readonlyフィールドに対する書き込み • 昔: 他の特殊化に対して初期化できる • C# 6.0: 自分自身だけを初期化できる public static class Foo<T> { static Foo() { if (typeof(T) == typeof(int)) { Foo<int>.compute = x => (int)x; } } public static readonly System.Func<double, T> compute; }
  63. 63. 日本人だけが気づく破壊的変更 • Unicodeの変更の影響 • 昔: カタカナ中点(中黒)OK • C# 6.0: Unicode側のミスでした。Unicodeが修正したらC#にも影響出ま した int x・y = 10; Console.WriteLine(x・y);
  64. 64. 微妙な新機能(1) • enumの基底型 • 昔: int, short, long など、キーワードでないとダメ • C# 6.0: Int32, Int16, Int64 など、System名前空間の型でもOK enum X : System.Int32 { A, B, C, }
  65. 65. 微妙な新機能(2) • オーバーロード解決ルールを改善 • 昔: ラムダ式の型推論、1段は行けてたけど2段は無理だった • C# 6.0: 2段以上もOK using System; class FuncOfFuncTypeInference { static void Main() { X(() => () => 10); } private static int X(Func<Func<int>> f) { return f()(); } private static int X(Func<Func<int?>> f) { return f()() ?? 0; } } int か int? か古いコンパイラーは判定できない
  66. 66. 追悼 • 一瞬、C# 6.0に入る予定だったもの • 互換性壊れるので取りやめたり • 引数なしの構造体コンストラクター • C# 7.0で改めて取り組むことになったり • プライマリ コンストラクター → レコード型 • 変数宣言式 → パターン マッチング
  67. 67. 追悼: 構造体の引数なしコンストラク ター • 構造体にも引数なしのコンストラクターを定義できるようにす るはずだった • .NETのランタイム レベルでバグがあることが発覚して断念 • Activator.CreateInstance<T>() が new T() をnullに置き換える struct MyInt { public readonly int Value; public MyInt() { Value = -1; } public MyInt(int value) { Value = value; } } 没
  68. 68. 追悼: プライマリ コンストラクター • 型定義の型名の直後にコンストラクターを1個書けた • 7.0でレコード型に吸収予定 class Immutable(int x) { public int X { get; } = x; } class Immutable(int x) { } 未 未
  69. 69. 追悼: 変数宣言式(declaration expressions) • 式の途中で変数宣言できた • 7.0でパターン マッチングと合わせて作り直す予定 while ((var line = Console.ReadLine()) != null) if (int.TryParse(line, out var x)) (var y = Math.Sin(x)) * y; if (x is string s) { … } else if (x is int n) { … } 未 未

×