Successfully reported this slideshow.
Your SlideShare is downloading. ×

(ゲームじゃない方の)switchで遊びたい話

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
20201127 .NET 5
20201127 .NET 5
Loading in …3
×

Check these out next

1 of 25 Ad

(ゲームじゃない方の)switchで遊びたい話

Download to read offline

2020-11-27開催の.NET 5 リリース記念 C# Tokyo イベント(https://csharp-tokyo.connpass.com/event/189415/)でのLT資料です。

2020-11-27開催の.NET 5 リリース記念 C# Tokyo イベント(https://csharp-tokyo.connpass.com/event/189415/)でのLT資料です。

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to (ゲームじゃない方の)switchで遊びたい話 (20)

Advertisement

Recently uploaded (20)

(ゲームじゃない方の)switchで遊びたい話

  1. 1. (ゲームじゃない方の) Switchで遊びたい話 masanori_msl@ .NET 5リリース記念 C# Tokyo イベント
  2. 2. About me  Name:Masui Masanori  Work:無茶ぶり処理班  Twitter:https://twitter.com/masanori_msl  Blog:http://mslgt.hatenablog.com/ https://dev.to/masanori_msl ※なおゲーム機の方は持ってません
  3. 3. 今回のお話 C# 7以降でSwitchが 色々パワーアップしてるらしい ...ので試してみた
  4. 4. いままで(定数パターン) class Program { static void Main(string[] args) { int id = 1; switch(id) { case 0: Console.WriteLine("Id was 0"); break; case 1: Console.WriteLine("Id was 1"); break; default: Console.WriteLine("Not found"); break; } } } これが実行される 定数を条件として処理を分岐
  5. 5. 新しく追加されたもの(型パターン) public record RecordSample(int Id, string Name); static void Main(string[] args) { RecordSample r = new (3, "Hello"); Play((object)r); } private static void Play(object target) { switch(target) { case RecordSample r: Console.WriteLine($"Record Id: {r.Id} Name: {r.Name}"); break; default: Console.WriteLine("Not found"); break; } } これが実行される • 型を条件として処理を分岐。変換が可能ならその分岐の処理が実行される + インスタンス生成 • 定数パターンと型パターンは混在できる
  6. 6. 型パターンはwhenでさらに細分化できる private static void Play(object target) { switch(target) { case RecordSample r when r.Id < 0: Console.WriteLine($"Record1 Id: {r.Id} Name: {r.Name}"); break; case RecordSample r when r.Id >= 1: Console.WriteLine($"Record2 Id: {r.Id} Name: {r.Name}"); break; case RecordSample r: Console.WriteLine($"Record Id: {r.Id} Name: {r.Name}"); break; default: Console.WriteLine("Not found"); break; } } これが実行される 変換が可能 + when の条件に合致すればその分岐の処理が実行される
  7. 7. さらに C# 8からはさらにswitch式が登場
  8. 8. いままで(switch文) static void Main(string[] args) { int id = 1; string message = GetMessage(id); } private static string GetMessage(int id) { switch(id) { case 0: return "ID was 0"; case 1: return "ID was 1"; default: return "Other"; } } これが実行される
  9. 9. switch式を使う static void Main(string[] args) { int id = 1; string message = id switch { 0 => "ID was 0", 1 => "ID was 1", _ => "Other" }; } これが実行される • 使えるのはswitch文と同様定数パターンと型パターン • 初見だとびっくりする(した)が、三項演算子やNull合体演算子を考えると納得できる気が
  10. 10. 疑問 whenをたくさん使うと インスタンスもたくさん作られる?
  11. 11. 先ほどのコード private static void Play(object target) { switch(target) { case RecordSample r when r.Id < 0: Console.WriteLine($"Record1 Id: {r.Id} Name: {r.Name}"); break; case RecordSample r when r.Id >= 1: Console.WriteLine($"Record2 Id: {r.Id} Name: {r.Name}"); break; case RecordSample r: Console.WriteLine($"Record Id: {r.Id} Name: {r.Name}"); break; default: Console.WriteLine("Not found"); break; } } target が RecordSample に変換できて、かつ Id = 0 だった場合、インスタンスは3つ作られる?
  12. 12. 答え 生成されるインスタンスは一つ
  13. 13. どう実行されるのか VS Code拡張版ILSpy先生に聞いてみた (https://marketplace.visualstudio.com/items?itemName=icsharpcode.ilspy-vscode)
  14. 14. こんな風になっているらしい private static void Play(object target) { RecordSample recordSample = target as RecordSample; if ((object)recordSample != null) { if (recordSample.Id < 0) { Console.WriteLine($"Record1 Id: ~省略~ return; } RecordSample recordSample2 = recordSample; if (recordSample2.Id >= 1) { Console.WriteLine($"Record2 Id: ~省略~ return; } RecordSample recordSample3 = recordSample; Console.WriteLine($"Record Id: ~省略~ } ~省略~
  15. 15. 詳しくはWebで パターン マッチング - C# ガイド | Microsoft Docs https://docs.microsoft.com/ja-jp/dotnet/csharp/pattern-matching switch 式 - C# リファレンス | Microsoft Docs https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/switch-expression パターン マッチング - C# によるプログラミング入門 | ++C++; // 未確認飛行 C https://ufcpp.net/study/csharp/datatype/patterns/ C# 8.0 パターン マッチング | ++C++; // 未確認飛行 C ブログ https://ufcpp.net/blog/2018/12/cs8patterns/ Do more with patterns in C# 8.0 | .NET Blog https://devblogs.microsoft.com/dotnet/do-more-with-patterns-in-c-8-0/ C# 8.0 - C# 8.0 でのパターン マッチング | Microsoft Docs https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2019/may/csharp-8-0-pattern-matching- in-csharp-8-0 Programming C# 8.0 https://www.oreilly.com/library/view/programming-c-80/9781492056805/
  16. 16. 少し遊んでみる TypeScriptっぽく変換してみたい
  17. 17. どういうことか TypeScript・・・というかJavaScriptは、 そのClass(or Type or Inteface)と同じプロパティを持っていれば、 同じものとしてふるまうことができる
  18. 18. ということでそれを真似してみる • RecordSample に直接変換できる場合は変換する • 変換できない場合でかつ同じプロパティを持っている場合は、 RecordSampleの同名のプロパティに値を入れたインスタンスを作る
  19. 19. 変換用のメソッドを作る public record RecordSample { public int Id { get; init; } public string Name { get; init; } = ""; public RecordSample(int id, string name) { Id = id; Name = name; } public static bool TryParse(object original, out RecordSample? result) { result = null; var type = original.GetType(); var idValue = type.GetProperty("Id")?.GetValue(original)?.ToString(); var nameValue = type.GetProperty("Name")?.GetValue(original)?.ToString(); if(idValue == null || nameValue == null) { return false; } if(int.TryParse(idValue, out var id) == false) { return false; } result = new RecordSample(id, nameValue); return true; } }
  20. 20. case を追加 private static void Play(object target) { switch(target) { case RecordSample r: Console.WriteLine($"Record Id: {r.Id} Name: {r.Name}"); break; case var o when RecordSample.TryParse(o, out var r): Console.WriteLine($"Property Id: {r!.Id} Name: {r!.Name}"); break; default: Console.WriteLine("Not found"); break; } } RecordSampleに変換できず、 かつ同じプロパティを持っていれば ここが実行されるはず
  21. 21. 呼び出し public class ClassSample { public int Id { get; set; } public string Name { get; set; } = ""; } static void Main(string[] args) { var c = new ClassSample { Id = 0, Name = "Hello" }; Play((object)c); } 同じプロパティを持つClassSampleというクラスを作って先ほどのswitchに渡す
  22. 22. 結果 Property Id: 0 Name: Hello
  23. 23. 疑問 どこで使おう?
  24. 24. 便利そうだけれども • あんまりobjectで渡して型変換ってしない気がする (ライブラリを作る場合は重宝するかも?) • switch式の方は細かく使えそうかも • ClosedXML(https://github.com/closedxml/closedxml)と 組み合わせると良さそう?
  25. 25. Thank you!

×