Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~

2020/02/14
「C#の新機能勉強会
~ C#7、8の新機能を活用して速く安全なプログラムを書こう~」

サンプル コード: https://github.com/Fujiwo/CSharp7_8NewFeatures
最新版: https://github.com/Fujiwo/CSharp7_8NewFeatures/blob/master/20200214_CSharp78.pdf

  • Be the first to comment

C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう~

  1. 1. C#の新機能勉強会 ~ C#7、8の新機能を活用して速く安全なプログラムを書こう ~ 2020/02/14 小島 富治雄
  2. 2. 前提条件とゴール 2
  3. 3. 開発環境 3
  4. 4. Visual Studio でプロジェクトを新規作成 4 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1 </TargetFramework> <Nullable>enable</Nullable> </PropertyGroup> </Project>
  5. 5. https://github.com/Fujiwo/CSharp7_8NewFeatures サンプル ソースコードや資料 5
  6. 6. サンプル ソースコードや資料 6 https://github.com/Fujiwo/CSharp7_8NewFeatures
  7. 7. アジェンダ
  8. 8. 1. C#/.NETの今と近未来 8
  9. 9. C# の歴史 C# Ver. 主な新機能 登場時期 .NET Visual Studio 1.0, 1.1, 1.2 オブジェクト指向 2002年 .NET Framework 1.0,1.1 .NET, .NET 2003 2.0 ジェネリック 2005年 .NET Framework 2.0 2005 3.0 関数型 2007年 .NET Framework 2.0, 3.0, 3.5 2008, 2010 4.0 動的 2010年 .NET Framework 4 2010 5.0 非同期 2012年 .NET Framework 4.5 2012, 2013 6.0 Roslyn (コンパイラーをC#で実装しオープンソース化) 2015年 .NET Framework 4.6 .NET Core 1.0 2015 7.0, 7.1, 7.2, 7.3 パターン マッチング、値型に関する改良 2017年 .NET Framework 4.6.2, 4.7, 4.7.1, 4.7.2 .NET Core 2.0, 2.1, 2.2 2017 8.0 値型、参照型に関する改良 2019年 .NET Core 3.0 2019 Ver.16.3
  10. 10. C# 7~8 10 C# Ver. Visual Studio 7.0 Visual Studio 2017 7.1 Visual Studio 2017 バージョン 15.3 7.2 Visual Studio 2017 バージョン 15.5 7.3 Visual Studio 2017 バージョン 15.7 8.0 Visual Studio 2019 16.3
  11. 11. C# 7~8 11 ターゲット フレーム バージョン C# 言語の既定の バージョン .NET Core 3.x C# 8.0 .NET Core 2.x C# 7.3 .NET Standard 2.1 C# 8.0 .NET Standard 2.0 C# 7.3 .NET Standard 1.x C# 7.3 .NET Framework all C# 7.3
  12. 12. プロジェクト ファイルでの C#のバージョン指定 12 <Project ……> <PropertyGroup> <OutputType>……</OutputType> <TargetFramework>……</TargetFramework> <!--……中略……--> <LangVersion>8.0</LangVersion> <Nullable>enable</Nullable> </PropertyGroup> <!--……中略……--> </Project> LangVersion 説明 preview 最新プレビュー バージョン latest 最新リリース バージョン (マイナー バージョンを含む) latestMajor 最新リリースの メジャー バージョン 8.0 C# 8.0
  13. 13. C# 8.0 13
  14. 14. 参考: .NET Framework と .NET Core 14
  15. 15. 参考: 今の .NET (2019年9月以降) 15 .NET Core が WPF と Windows Forms をサポート (Windows 版のみ) .NET Framework 4.8.X • WPF • Windows Forms • ASP.NET .NET Core 3.X • WPF (Windows) • Windows Forms (Windows) • ASP.NET Xamarin • iOS • Android • Windows • MacOS .NET Standard Library
  16. 16. 参考: 近未来の .NET (2020年11月予定) 16 .NET Core が WPF と Windows Forms をサポート (Windows 版のみ) .NET Framework 4.8.X • WPF • Windows Forms • ASP.NET .NET 5.0 • WPF (Windows) • Windows Forms (Windows) • UWP (Windows) • ASP.NET Xamarin • iOS • Android • Windows • MacOS .NET Standard Library 保守フェーズに
  17. 17. C# 7~8の新機能の例 17 タプル 値型 (struct) パターン マッチング 参照型 (class) その他
  18. 18. C# 7~8の新機能 18
  19. 19. 2. C# の値型と参照型 19
  20. 20. C#に潜むstructの罠 – KAYAC engineers‘ blog C#に潜むstructの罠? 20 お急ぎの方のために 結論を申しあげますと、 そんなわけありません。 なんで C# に値型が あるかが分かっていない。
  21. 21. 復習: structを使うときの注意点 21 • https://github.com/Fujiwo/CSharp7_8NewFeatures • サンプル コード
  22. 22. 復習: スタック領域とヒープ領域 22 コード領域 スタティック領域 (静的変数) スタック領域 (自動変数、メソッド コール) ヒープ領域 (動的確保) データ領域
  23. 23. 復習: スタック領域 23 int Add(int x, int y) // C++、x64、最適化なし { auto answer = x + y; return answer; 64bits スタック ポインター レジスター
  24. 24. 復習: スタック領域とヒープ領域 24 スタック領域 ヒープ領域 struct FooStruct { /* ...省略... */ } class FooClass { /* ...省略... */ } static void Main() { FooStruct fooStruct1; var fooStruct2 = new FooStruct(); var fooClass = new FooClass (); }
  25. 25. 復習: スタック領域とヒープ領域 25
  26. 26. C#の参照型 (class) 26 class FooClass { public int Id { get; set; } = 0; public int Value { get; set; } = 1; }
  27. 27. C#の値型 (struct) 27 struct FooStruct { public int Id { get; set; } public int Value { get; set; } }
  28. 28. 値型 (struct) と参照型 (class) の例 28 これからは原則値型 (struct) の方を使おう! 自作の型も同様。 「struct 使うな」はあり得ない。
  29. 29. 値型 (struct) を使うコツ 29 readonly struct Point { public readonly double X; public readonly double Y; public Point(double x, double y) => (X, Y) = (x, y); }コピーせず参照で高速にアクセスしつつも、 元の値を変更される危険を回避
  30. 30. いつのまにかヒープ領域が使われてしまう例 30 Enumerable.Range(minimum, maximum) .ForEach(value => sum += value);
  31. 31. 暗黙の new 31
  32. 32. 値型 (struct) はなるべく immutable に使う 32 readonly struct Point { public readonly double X; public readonly double Y; public Point(double x, double y) => (X, Y) = (x, y); public double AbsoluteValue => Math.Sqrt(X * X + Y * Y); public readonly double DotProduct(Point another) => X * another.X + Y * another.Y; }
  33. 33. 3. C# プログラムの高速化 33
  34. 34. • 時間の掛かる処理 (I/O、ネットワーク、重い計算) は非同期・別スレッドで 高速化 34
  35. 35. ツール: パフォーマンス プロファイラー 35
  36. 36. ツール: BenchmarkDotNet 36
  37. 37. ツール: BenchmarkDotNet 37 using BenchmarkDotNet.Attributes; using System.Linq; class Program { static void Main() => BenchmarkRunner.Run<SampleBenchMark>(); } [ShortRunJob][HtmlExporter][CsvExporter] public class SampleBenchMark { const int count = 10000; int[] array = new int[0]; [GlobalSetup] public void Setup() => array = Enumerable.Range(0, count).ToArray(); [Benchmark] public int 配列をforして合計を求める() { var sum = 0; for (var index = 0; index < array.Length; index++) sum += array[index]; return sum; } [Benchmark] public int 配列をforeachして合計を求める() { var sum = 0; foreach (var element in array) sum += element; return sum; } }
  38. 38. ツール: BenchmarkDotNet 38 • https://github.com/Fujiwo/CSharp7_8NewFeatures • サンプル コード 測定結果1 (xlsx ファイル) 測定結果2 (xlsxファイル)
  39. 39. struct を interface で受けると… 39 interface IValuable { int GetValue(); } struct FooStruct : IValuable { public int Value { get; set; } public int GetValue() => Value; } public int interfaceを渡す非ジェネリック版() { var item = new FooStruct { Value = 0 }; var sum = 0; for (var count = 0; count < Size; count++) sum += interfaceを受け取る非ジェネリック版(item); return sum; } static int interfaceを受け取る非ジェネリック版 (IValuable item) => item.GetValue(); public int interfaceを渡すジェネリック版() { var item = new FooStruct { Value = 0 }; var sum = 0; for (var count = 0; count < Size; count++) sum += interfaceを受け取るジェネリック版(item); return sum; } static int interfaceを受け取るジェネリック版<T>(T item) where T : IValuable => item.GetValue();
  40. 40. ツール: BenchmarkDotNet 40
  41. 41. 非ジェネリック版のコレクションを使うと… 41 struct FooStruct { public int Value { get; set; } } public int 非ジェネリック版Collection() { var list = new ArrayList(); for (var count = 0; count < Size; count++) list.Add(new FooStruct { Value = 0 }); var sum = 0; for (var index = 0; index < list.Count; index++) sum += ((FooStruct)list[index]).Value; return sum; } public int ジェネリック版Collection() { var list = new List<FooStruct>(); for (var count = 0; count < Size; count++) list.Add(new FooStruct { Value = 0 }); var sum = 0; for (var index = 0; index < list.Count; index++) sum += list[index].Value; return sum; }
  42. 42. ツール: BenchmarkDotNet 42
  43. 43. static int var for var return static int ListをCountを変数にしてからforする(List<Foo> foos) { var sum = 0; var count = foos.Count; for (var index = 0; index < count; index++) sum += foos[index].Value; return sum; } static int Listをforeachする(List<Foo> foos) { var sum = 0; foreach (var foo in foos) sum += foo.Value; return sum; } for/foreach の速度 43
  44. 44. for/foreach の速度 44
  45. 45. for/foreach の速度 45 // Enumerator が値型 (struct) の配列 public struct ClassEnumeratorArray<T> : IEnumerable<T> { readonly T[] array; public StructEnumeratorArray(T[] array) => this.array = array; public Enumerator GetEnumerator() => new Enumerator(array); public class Enumerator : IEnumerator<T> { readonly T[] array; int index; internal Enumerator(T[] array) => (this.array, index) = (array, -1); public T Current => array[index]; object? IEnumerator.Current => Current; public bool MoveNext() => ((uint)++index) < (uint)array.Length; public void Dispose() {} public void Reset() => index = -1; } } サンプル コード
  46. 46. for/foreach の速度 46 // Enumerator が値型 (struct) の配列 public struct StructEnumeratorArray<T> { readonly T[] array; public StructEnumeratorArray(T[] array) => this.array = array; public Enumerator GetEnumerator() => new Enumerator(array); public struct Enumerator : IEnumerator<T> { readonly T[] array; int index; internal Enumerator(T[] array) => (this.array, index) = (array, -1); public T Current => array[index]; object? IEnumerator.Current => Current; public bool MoveNext() => ((uint)++index) < (uint)array.Length; public void Dispose() {} public void Reset() => index = -1; } } サンプル コード
  47. 47. for/foreach の速度 47
  48. 48. 36倍!
  49. 49. ツール: ILSpy 49
  50. 50. ツール: LINQPad 50 https://www.linqpad.net
  51. 51. https://sharplab.io ツール: SharpLab 51
  52. 52. 4. C# 7、8の新機能 52
  53. 53. 53 C# 7、8の新機能 もう「structを使うな」 などと言わせない
  54. 54. 安全に 54 C# 7、8の新機能
  55. 55. C# 7、8の新機能 55 • https://github.com/Fujiwo/CSharp7_8NewFeatures • サンプル コード
  56. 56. タプル (ValueTuple) 56 static int Compare(int? x, int? y) { switch ((x, y)) { case (int value1, int value2): return value1.CompareTo(value2); case ({} , null ): case (null , {} ): case (null , null ): return 0; } }
  57. 57. 分解と Deconstruct 57 var answer = (dividend / divisor, dividend % divisor); var (quotient, remainder) = answer; var staff = new Person(id: 100, name: "志垣太郎"); var (id, name) = staff;
  58. 58. 参照渡し/参照返し 58
  59. 59. Span 59 unsafe { int* array = stackalloc int[size]; for (var index = 0; index < size; index++) array[index] = index; } Span<int> array = stackalloc int[size]; for (var index = 0; index < array.Length; index++) array[index] = index;
  60. 60. ローカル関数 60 static int ToDecimal(this IEnumerable<int> @this) { var number = 0; // ローカル関数 (number をキャプチャー) void Add(int digit) => number = number * 10 + digit; @this.ForEach(Add); return number; } ラムダ式と 違って…
  61. 61. null 許容参照型 61 #nullable enable public class Foo { } #nullable restore <Nullable>enable</Nullable> s ??= "default string";
  62. 62. パターンマッチング 62 static bool IsNullOrSpace(string? text) => text switch { null => true , string { Length: 0 } => true , string s when s.Trim().Length == 0 => true , _ => false };
  63. 63. インターフェイスのデフォルト実装 63 // インターフェイスのデフォルト実装 interface IEnumerable改<TElement> : IEnumerable<TElement> { IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }
  64. 64. 非同期ストリーム 64 static async IAsyncEnumerable<TResult> SelectAsync<TElement, TResult>( // 非同期ストリーム this IAsyncEnumerable<TElement> @this, Func<TElement, TResult> selector ) { // 非同期foreach await foreach (var item in @this) // 非同期イテレーター yield return selector(item); }
  65. 65. その他 65
  66. 66. 本日の内容
  67. 67. C# | Wikipedia C# の歴史 - C# ガイド | Microsoft Docs C# 7 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C C# 7.1 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C C# 7.2 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C C# 7.3 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C C# 8.0 の新機能 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C 今日からできる! 簡単 .NET 高速化 Tips | slideshare foreach の掛け方いろいろ | ++C++; // 未確認飛行 C ブログ 参考文献 67

×