「C Sharpその他 - 使用すべき機能」の版間の差分
		
		
		
		
		
		ナビゲーションに移動
		検索に移動
		
				
		
		
	
| 編集の要約なし | 細 (文字列「</source>」を「</syntaxhighlight>」に置換) | ||
| (同じ利用者による、間の3版が非表示) | |||
| 20行目: | 20行目: | ||
| *: EAPは、結果をイベントで返すものである。末尾がAsyncのメソッドとCompletedのイベントのペアを使用する。 | *: EAPは、結果をイベントで返すものである。末尾がAsyncのメソッドとCompletedのイベントのペアを使用する。 | ||
| *: 例えば、WebClientクラス(System.Net名前空間)が、EAP型の非同期APIを持っている。 | *: 例えば、WebClientクラス(System.Net名前空間)が、EAP型の非同期APIを持っている。 | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   var wc = new WebClient { Encoding = Encoding.UTF8 }; |   var wc = new WebClient { Encoding = Encoding.UTF8 }; | ||
| 30行目: | 30行目: | ||
|   wc.DownloadStringAsync(new Uri("http://ufcpp.net/study/csharp/")); |   wc.DownloadStringAsync(new Uri("http://ufcpp.net/study/csharp/")); | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| * C# 4.0の記述方法 | * C# 4.0の記述方法 | ||
| 38行目: | 38行目: | ||
| *: .NET Framework 4.5では、標準ライブラリ中の非同期APIにTAP版が用意されている。 | *: .NET Framework 4.5では、標準ライブラリ中の非同期APIにTAP版が用意されている。 | ||
| *: 例えば、WebRequestクラスのメソッドにも、TAP版が用意されます。 | *: 例えば、WebRequestクラスのメソッドにも、TAP版が用意されます。 | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   var req = WebRequest.Create("http://ufcpp.net/study/csharp/"); |   var req = WebRequest.Create("http://ufcpp.net/study/csharp/"); | ||
|   req.GetResponseAsync().ContinueWith(t => |   req.GetResponseAsync().ContinueWith(t => | ||
| 51行目: | 51行目: | ||
|                                         Console.WriteLine(result); |                                         Console.WriteLine(result); | ||
|                                      }); |                                      }); | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| * C# 5.0の記述方法 | * C# 5.0の記述方法 | ||
| *: C# 5.0では、さらに、非同期処理を、同期版と同じ構造のままで記述できるasync / awaitという機能が追加された。 | *: C# 5.0では、さらに、非同期処理を、同期版と同じ構造のままで記述できるasync / awaitという機能が追加された。 | ||
| *: 上記の例を、async /awaitを使用して記述し直すと、以下のようになる。 | *: 上記の例を、async /awaitを使用して記述し直すと、以下のようになる。 | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   private static async Task SampleAsync() |   private static async Task SampleAsync() | ||
|   { |   { | ||
| 71行目: | 71行目: | ||
|      } |      } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| ===== LINQ ===== | ===== LINQ ===== | ||
| 79行目: | 79行目: | ||
| *: イテレータ構文もLINQも無い場合は、以下のように記述していた。 | *: イテレータ構文もLINQも無い場合は、以下のように記述していた。 | ||
| *: この記述方法では、一時的にListを生成しているので、データ量が増加すると、多くのメモリを消費する。 | *: この記述方法では、一時的にListを生成しているので、データ量が増加すると、多くのメモリを消費する。 | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   using System; |   using System; | ||
|   using System.Collections.Generic; |   using System.Collections.Generic; | ||
| 128行目: | 128行目: | ||
|      } |      } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| * 現在の記述方法 | * 現在の記述方法 | ||
| *: イテレータ構文とLINQを使用して、一時的なListクラスを生成しない。 | *: イテレータ構文とLINQを使用して、一時的なListクラスを生成しない。 | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   using System; |   using System; | ||
|   using System.Collections.Generic; |   using System.Collections.Generic; | ||
| 171行目: | 171行目: | ||
|      } |      } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| ===== IEnumerableを使う ===== | ===== IEnumerableを使う ===== | ||
| <span style="color:#C00000">'''ポイント : メソッドの引数や戻り値、プロパティの型には、IEnumerable<T> を使う。'''</span><br> | <span style="color:#C00000">'''ポイント : メソッドの引数や戻り値、プロパティの型には、IEnumerable<T> を使う。'''</span><br> | ||
| データ列に対して、前から順に1要素ずつ読む操作のみを行う場合、List<T>クラスや配列ではなく、IEnumerable<T>インターフェイスを使う。<br> | データ列に対して、前から順に1要素ずつ読む操作のみを行う場合、List<T>クラスや配列ではなく、IEnumerable<T>インターフェイスを使う。<br> | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   // ダメなコード |   // ダメなコード | ||
|   // この記述では、配列の内容を書き換えられる |   // この記述では、配列の内容を書き換えられる | ||
| 189行目: | 189行目: | ||
|      } |      } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   // 良いコード |   // 良いコード | ||
|   // 読み取り専用なら、IEnumerableにする |   // 読み取り専用なら、IEnumerableにする | ||
| 204行目: | 204行目: | ||
|      } |      } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| ===== XML ===== | ===== XML ===== | ||
| 217行目: | 217行目: | ||
| *: .NET 3.5から、XDocumentクラスが追加された。IEnumerable<XElement>で要素一覧を読み出せるので、LINQ to Objectsが使える。 | *: .NET 3.5から、XDocumentクラスが追加された。IEnumerable<XElement>で要素一覧を読み出せるので、LINQ to Objectsが使える。 | ||
| <br> | <br> | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   var doc = XDocument.Load(filename); |   var doc = XDocument.Load(filename); | ||
|   var ns = doc.Root.Name.Namespace; |   var ns = doc.Root.Name.Namespace; | ||
| 228行目: | 228行目: | ||
|      Console.WriteLine(title); |      Console.WriteLine(title); | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| ===== 自動実装プロパティ ===== | ===== 自動実装プロパティ ===== | ||
| 234行目: | 234行目: | ||
| 後からの変更に備えて、ただフィールドを読み書きするだけのプロパティを作ることがある。<br> | 後からの変更に備えて、ただフィールドを読み書きするだけのプロパティを作ることがある。<br> | ||
| 下記のようにすれば、後から処理を加えることになっても、 クラスの利用側の再コンパイルは不要である。<br> | 下記のようにすれば、後から処理を加えることになっても、 クラスの利用側の再コンパイルは不要である。<br> | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   private int _x; |   private int _x; | ||
| 244行目: | 244行目: | ||
|      //set { _x = value; } |      //set { _x = value; } | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br> | <br> | ||
| また、外部からは読み取り専用なプロパティを作る場合は、以下のように記述する。<br> | また、外部からは読み取り専用なプロパティを作る場合は、以下のように記述する。<br> | ||
|   < |   <syntaxhighlight lang="c#"> | ||
|   public int X |   public int X | ||
|   { |   { | ||
| 253行目: | 253行目: | ||
|      private set; |      private set; | ||
|   } |   } | ||
|   </ |   </syntaxhighlight> | ||
| <br><br> | <br><br> | ||
| __FORCETOC__ | __FORCETOC__ | ||
| [[カテゴリ:C_Sharp]] | [[カテゴリ:C_Sharp]] | ||
2021年11月24日 (水) 18:08時点における最新版
概要
新しい構文やライブラリが導入されたことで、記述方法が変わったものがある。
ここでは、その記述方法をまとめる。
使用すべき機能
マルチスレッド
ポイント : Taskクラスを使う。
時間がかかる処理は、マルチスレッドにすべきである。
特に、ネットワーク処理等、待ち時間の長い処理にはマルチスレッドが必須である。
- 以前(C# 1.0 / 1.1)の記述方法
- C# 1.0 / 1.1では、APM(Asynchronous Programming Model)というものがある。
- APMは、IAsyncResultを返すまたは受け取るBegin / Endメソッドのペアを使用する。
- 例えば、WebRequestクラス(System.Net名前空間)は、APM型の非同期APIを持っている。
- ここでは、サンプルコードは割愛する。
 
- 以前(C# 2.0)の記述方法
- C# 2.0では、EAP(Event-based Asynchronous Pattern)という記述方法が流行った。
- EAPは、結果をイベントで返すものである。末尾がAsyncのメソッドとCompletedのイベントのペアを使用する。
- 例えば、WebClientクラス(System.Net名前空間)が、EAP型の非同期APIを持っている。
 
 var wc = new WebClient { Encoding = Encoding.UTF8 };
 
 wc.DownloadStringCompleted += (sender, args) =>
 {
    var result = args.Result;
    Console.WriteLine(result);
 };
 
 wc.DownloadStringAsync(new Uri("http://ufcpp.net/study/csharp/"));
- C# 4.0の記述方法
- APMやEAPでは、複数の非同期処理を繋いで、1つの非同期APIにする作業が面倒だった。
- .NET Framework 4.0で導入されたTaskクラスでは、複数の非同期処理を繋ぐことが簡潔に記述できるようになった。
- そこで、非同期APIも、Taskクラスを返すメソッドを1つだけ用意するTAP(Task-based Asynchronous Pattern)という記述方法が今後の主流になる。
- .NET Framework 4.5では、標準ライブラリ中の非同期APIにTAP版が用意されている。
- 例えば、WebRequestクラスのメソッドにも、TAP版が用意されます。
 
 var req = WebRequest.Create("http://ufcpp.net/study/csharp/");
 req.GetResponseAsync().ContinueWith(t =>
                                    {
                                       var res = t.Result;
 
                                       string result = null;
                                       using (var reader = new StreamReader(res.GetResponseStream()))
                                       {
                                          result = reader.ReadToEnd();
                                       }
                                       Console.WriteLine(result);
                                    });
- C# 5.0の記述方法
- C# 5.0では、さらに、非同期処理を、同期版と同じ構造のままで記述できるasync / awaitという機能が追加された。
- 上記の例を、async /awaitを使用して記述し直すと、以下のようになる。
 
 private static async Task SampleAsync()
 {
    using(var req = WebRequest.Create(@"http://ufcpp.net/study/csharp/"))
    {
       var res = await req.GetResponseAsync();
 
       string result = null;
       using (var reader = new StreamReader(res.GetResponseStream()))
       {
          result = reader.ReadToEnd();
       }
       Console.WriteLine(result);
    }
 }
LINQ
ポイント: LINQ を使えば、不要な一時リストを使わない。
データを入力、加工後、集計して表示したいサンプルコードを以下に示す。
- 以前の記述方法
- イテレータ構文もLINQも無い場合は、以下のように記述していた。
- この記述方法では、一時的にListを生成しているので、データ量が増加すると、多くのメモリを消費する。
 
 using System;
 using System.Collections.Generic;
 
 class Program
 {
    static void Main()
    {
       var inputs = ReadIntFromConsole();
       var mapped = Square(inputs);
 
       foreach (var y in mapped)
       {
          Console.WriteLine("入力の二乗: {0}", y);
       }
    }
 
    static IEnumerable<int> ReadIntFromConsole()
    {
       var list = new List<int>();
       while (true)
       {
          var line = Console.ReadLine();
 
          if (string.IsNullOrWhiteSpace(line))
          {
             break;
          }
 
          int x;
          if (!int.TryParse(line, out x))
          {
                break;
          }
          list.Add(x);
       }
       return list;
    }
 
    static IEnumerable<int> Square(IEnumerable<int> source)
    {
       var list = new List<int>();
       foreach (var x in source)
       {
          list.Add(x * x);
       }
       return list;
    }
 }
- 現在の記述方法
- イテレータ構文とLINQを使用して、一時的なListクラスを生成しない。
 
 using System;
 using System.Collections.Generic;
 using System.Linq;
 
 class Program
 {
    static void Main()
    {
       var inputs = ReadIntFromConsole();
       var mapped = inputs.Select(x => x * x);
 
       foreach (var y in mapped)
       {
          Console.WriteLine("入力の二乗: {0}", y);
       }
    }
 
    static IEnumerable<int> ReadIntFromConsole()
    {
       while (true)
       {
          var line = Console.ReadLine();
 
          if (string.IsNullOrWhiteSpace(line))
          {
             break;
          }
 
          int x;
          if (!int.TryParse(line, out x))
          {
             break;
          }
          yield return x; // イテレータ構文
        }
    }
 }
IEnumerableを使う
ポイント : メソッドの引数や戻り値、プロパティの型には、IEnumerable<T> を使う。
データ列に対して、前から順に1要素ずつ読む操作のみを行う場合、List<T>クラスや配列ではなく、IEnumerable<T>インターフェイスを使う。
 // ダメなコード
 // この記述では、配列の内容を書き換えられる
 static readonly int[] SampleData = { 1, 2, 3, 4, 5 };
 
 // 読み取り専用にも関わらず、int[]で受け取っている
 static void Output(int[] data)
 {
    foreach (var x in data)
    {
       Console.WriteLine(x);
    }
 }
 // 良いコード
 // 読み取り専用なら、IEnumerableにする
 static readonly IEnumerable<int> SampleData = { 1, 2, 3, 4, 5, };
 
 // 上記と同様に、引数の型もIEnumerableにする
 static void Output(IEnumerable<int> data)
 {
    foreach (var x in data)
    {
       Console.WriteLine(x);
    }
 }
XML
ポイント : XDocumentクラス(System.Xml.Linq名前空間)を使う。
C# 3.0/.NET 3.5にて、LINQが導入されたことで、データ処理においてIEnumerable<T>インターフェイスが特別な意味を持つようになった。
それに合わせて、XMLの読み書きのためにも、IEnumerableでXML要素一覧を読み出せるようなクラスが新たに追加された。
- 以前の記述方法
- .NET 3.0以前では、XmlDocumentクラス(System.Xml名前空間)を使っていた。
 
- 現在の記述方法
- .NET 3.5から、XDocumentクラスが追加された。IEnumerable<XElement>で要素一覧を読み出せるので、LINQ to Objectsが使える。
 
 var doc = XDocument.Load(filename);
 var ns = doc.Root.Name.Namespace;
 
 var titles = from x in doc.Root.Elements(ns + "section")
              select x.Attribute("title").Value;
 
 foreach (var title in titles)
 {
    Console.WriteLine(title);
 }
自動実装プロパティ
ポイント : フィールドをpublicにしてはいけない。自動実装プロパティを使用する。
後からの変更に備えて、ただフィールドを読み書きするだけのプロパティを作ることがある。
下記のようにすれば、後から処理を加えることになっても、 クラスの利用側の再コンパイルは不要である。
 private int _x;
 
 public int X
 {
    get;
    set;
    //get { return _x; }
    //set { _x = value; }
 }
また、外部からは読み取り専用なプロパティを作る場合は、以下のように記述する。
 public int X
 {
    get;
    private set;
 }