C# 2.0 以降の新機能の名前と公式ガイドページへのリンクをまとめました。(C# 2.0 ~ 6.0)
注1)機能の名前はできるだけ公式ガイドから言葉を拾うようにしましたが、完全ではありません。
注2)リンク先としてよいページを見つけられていないものもあります。
注3)良さそうなページを探しましたが、もっと良いページがあるかもしれません。
■ C# 2.0 での新機能
・ジェネリック
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/generics/
List<T> クラスなどの T の機能。List<int> とすると int 型しか格納できない型安全な List を使用できる。
List<int> ints = new List<int>();
ints.Add(1);
List<string> strings = new List<string>();
strings.Add("text");
・匿名メソッド
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/anonymous-methods
[推奨されません(※)] delegate をインライン コードで生成できる。 (※)C# 3.0 で追加されたラムダ式を使用してください。
System.Threading.Timer t = new System.Threading.Timer(
delegate (object state) { Console.WriteLine("delegate"); }
, null, 0, 1000
);
・反復子 (yield)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/iterators
反復子を使用して、リストや配列などのコレクションをステップ実行することができる。
static void Main(string[] args)
{
foreach (int number in Values())
{
Console.WriteLine(number.ToString());
}
}
public static IEnumerable<int> Values()
{
yield return 1;
yield return 2;
yield return 3;
}
・部分型定義 (Partial クラス/構造体)
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/partial-type
クラス、構造体、またはインターフェイスの定義を複数のファイルに分割することができる。
class Program
{
static void Main(string[] args)
{
A a = new A();
a.A1();
a.A2();
}
}
partial class A
{
public void A1()
{
Console.WriteLine("A1");
}
}
partial class A
{
public void A2()
{
Console.WriteLine("A2");
}
}
・Null 許容型 (Nullable)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/nullable-types/
Null 許容型は、基になる値型の値だけでなく、null 値も表すことができる。型名の後ろに ? をつけて変数宣言する。Value プロパティ等で値型で値を取り出せるが、多くの場所で Null 許容型のままでも期待する結果になる。
int? a = 1;
a = null;
Console.WriteLine(a == null);
a = 1;
Console.WriteLine(a.Value);
Console.WriteLine(a);
・?? 演算子
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/null-conditional-operator
null 合体演算子と呼ばれる。左側のオペランドが null 値でない場合には左側のオペランドを返し、null 値である場合には右側のオペランドを返す。
string a = "a";
string b = null;
Console.WriteLine(a ?? "a is null");
Console.WriteLine(b ?? "b is null");
・プロパティの get/set 個別のアクセスレベル
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/restricting-accessor-accessibility
プロパティの get アクセサーと set で異なるアクセス レベルを設定できる。
class Program
{
static void Main(string[] args)
{
A a = new A();
a.SetPropertyA(10);
Console.WriteLine(a.PropertyA);
}
}
class A
{
public int PropertyA { get; private set; }
public void SetPropertyA(int value) { PropertyA = value; }
}
・static クラス
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members
new キーワードを使用して、そのクラス型の変数を作成できないクラスを定義できる。class の前に static をつける。
class Program
{
static void Main(string[] args)
{
A.PropertyA = 1;
Console.WriteLine(A.PropertyA);
}
}
static class A
{
public static int PropertyA { get; set; }
}
・:: 演算子
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/namespace-alias-qualifer
名前を検索する名前空間エイリアスを指定する。global キーワードを指定すると、常にグローバル名前空間で検索が実行される。
using A = B;
class Program
{
static void Main(string[] args)
{
global::A.WriteLine();
A::C.WriteLine();
}
}
class A
{
internal static void WriteLine()
{
System.Console.WriteLine("A");
}
}
namespace B
{
class C
{
internal static void WriteLine()
{
System.Console.WriteLine("C");
}
}
}
・extern エイリアス
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/extern-alias
同じ完全修飾型名を持つ、2 つアセンブリを参照する場合に名前空間のエイリアスを設定できる。
次の例では同じ名前の ClassLibrary.Class1.WriteLine()
を持つ a.dll に A というエイリアスを、b.dll に B というエイリアスをつけるています。
手順
- ソリューション エクスプローラーで実行プロジェクトの依存関係の中のクラスライブラリ プロジェクト (dll) のプロパティを開きます。
- エイリアスにそれぞれ a.dll プロジェクトには A、b.dll プロジェクトには B と設定します。
- 実行プロジェクト内でソースファイルの先頭に
extern alias A;
extern alias B;
を追加します。これで A 名前空間エイリアスと B 名前空間エイリアスが使えるようになります。
- :: 演算子を使用した名前空間エイリアスを指定でメソッドを呼びます。
extern alias A;
extern alias B;
class Program
{
static void Main(string[] args)
{
A::ClassLibrary.Class1.WriteLine();
B::ClassLibrary.Class1.WriteLine();
}
}
a.dll
namespace ClassLibrary
{
public class Class1
{
public static void WriteLine()
{
Console.WriteLine("A");
}
}
}
b.dll
namespace ClassLibrary
{
public class Class1
{
public static void WriteLine()
{
Console.WriteLine("B");
}
}
}
・#pragma プリプロセッサディレクティブ
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-pragma
特殊な命令をコンパイラに指示できる。
#pragma warning disable 警告の番号
で指定した番号の警告が表示されないようにできる。#pragma warning restore 警告の番号
で警告が出るようになる。警告の番号は複数指定することも省略することも可能。省略した場合はすべての警告が非表示/表示になる。
#pragma warning disable CS0168
int i;
#pragma warning restore CS0168
int j;
・Conditional 属性
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/attributes/general#conditional-attribute
条件付きコンパイル シンボルによる条件付きメソッドを定義ができる。シンボルが定義されていない場合、メソッドの呼び出しが行われない。
条件付きコンパイル シンボルについての詳細は次のページがわかりやすそうです。
ConditionalAttribute クラス (System.Diagnostics) | Microsoft Docs
次の例では、プロジェクトのプロパティ > ビルド > DEBUG 定数の定義
を ON にしているかデバッグ実行の際にのみ Debug Mode が出力されます。
static void Main(string[] args)
{
WriteDebug();
}
[System.Diagnostics.Conditional("DEBUG")]
public static void WriteDebug()
{
Console.WriteLine("Debug Mode");
}
・固定サイズ バッファー (fixed)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/unsafe-code-pointers/fixed-size-buffers
DLL や COM を扱う際に使える、固定サイズの配列を持ったバッファーを作成することができる。
public fixed char fixedBuffer[128];
・デリゲートの分散 (共変性と反変性)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/covariance-contravariance/using-variance-in-delegates
共変性により、メソッドの戻り値の型をデリゲートに定義されている型のサブクラスにできる。 反変性によりメソッドのパラメーター型をデリゲートのパラメーターの型のスーパークラスにできる。
class Program
{
class A { }
class A2 : A { }
class A22 : A2 { }
class A3 : A { }
delegate A2 MyDelegate(A2 a2);
static void Main(string[] args)
{
MyDelegate deleg1 = Method1;
A a = deleg1(new A2());
}
static A22 Method1(A a) { return null; }
static A2 Method2(A3 a) { return null; }
static A Method3(A2 a) { return null; }
}
■ C# 3.0 での新機能
・型推論 (var)
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/var
変数の宣言時に暗黙の型指定を行える。コンパイラが型を推論してくれる。
var i = 10;
i = 20;
・配列の型推論 (暗黙的に型指定される配列)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/arrays/implicitly-typed-arrays
配列の宣言時に暗黙の型指定を行える。コンパイラが型を推論してくれる。
var ints = new[] { 0, 20, 30 };
ints[0] = 10;
foreach(var i in ints)
{
Console.WriteLine(i);
}
・自動実装プロパティ
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
値の取得または設定時にロジックが必要ない場合、プロパティを簡潔に宣言できる。
class Program
{
static void Main(string[] args)
{
Phone p = new Phone();
p.Name = "窓スマ";
p.Size = 5.0;
Console.WriteLine(string.Format("{0}, {1} インチ",p.Name, p.Size));
}
}
class Phone
{
internal string Name { get; set; }
internal double Size { get; set; }
}
・拡張メソッド
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/extension-methods
既存の型に外からメソッドを追加できる(実際に追加されるわけではなく、追加されたかのようにコードを書ける)。
次の例では、string クラスに HasValue メソッドが追加されたかのようにコードが書けている。
class Program
{
static void Main(string[] args)
{
string s = "text";
Console.WriteLine(s.HasValue());
s = null;
Console.WriteLine(s.HasValue());
}
}
static class StringExtensions
{
internal static bool HasValue(this string value)
{
return !string.IsNullOrEmpty(value);
}
}
・ラムダ式
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions
匿名関数。引数として渡したり関数呼び出しの結果値として返すことができるローカル関数を記述できる。あらゆる場所で使われるが、LINQ を使用する際に特に重要。
System.Threading.Timer t = new System.Threading.Timer(
state => Console.WriteLine("lambda")
,null, 0, 1000
);
・LINQ
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq
データソースからデータを取得する。その際、変換や集計、グループ化などを行うことも可能。クエリ式とメソッド式という 2 つの形式があるが、一般にメソッド式が使われる。下記はメソッド式の例。
int[] data = new[] { 1, 2, 3, 4, 5, 6 };
var evens = data.Where(x => x % 2 == 0);
foreach (var i in evens)
{
Console.Write(i);
}
var ws = data.Select(x => x * 2);
foreach (var i in ws)
{
Console.Write(i);
}
var evensws = data.Where(x => x % 2 == 0).Select(x => x * 2);
foreach (var i in evensws)
{
Console.Write(i);
}
Console.WriteLine(data.Max());
Console.WriteLine(data.Min());
Console.WriteLine(data.Sum());
・匿名型
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types
明示的に型を定義することなく、複数の読み取り専用プロパティを持ったオブジェクトを生成できる。 各プロパティの型はコンパイラにより推論される。
var p = new { Name = "窓スマ", Size = 5.0 };
Console.WriteLine(string.Format("{0}, {1} インチ", p.Name, p.Size));
Console.WriteLine(string.Format("p is {0}", p.GetType().Name));
Console.WriteLine(string.Format("Name is {0}", p.Name.GetType().Name));
Console.WriteLine(string.Format("Size is {0}", p.Size.GetType().Name));
・オブジェクト初期化子
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers
オブジェクトの作成時にプロパティに、値を割り当てることができる。匿名型の使用時にも使われる。
class Program
{
static void Main(string[] args)
{
MyPoint p = new MyPoint() { X = 10, Y = 20 };
Console.WriteLine(string.Format("{0}, {1}", p.X, p.Y));
var anonymous = new[] { 1, 2, 3 }.Select(x => new { Source = x, W = x * 2 });
foreach(var m in anonymous)
{
Console.WriteLine(string.Format("{0}, {1}", m.Source, m.W));
}
}
}
class MyPoint
{
internal int X { get; set; }
internal int Y { get; set; }
}
・Partial メソッド
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/partial-method
Partial クラスの定義時にメソッドのシグネチャと実装を分けられる。定義できるメソッドは void を返す private メソッドのみ。
class Program
{
static void Main(string[] args)
{
new A().Method();
Console.WriteLine("=====");
new B().Method();
}
}
partial class A
{
internal void Method()
{
this.PartialMethod("Class A Method");
}
partial void PartialMethod(string text);
}
partial class A
{
}
partial class B
{
internal void Method()
{
this.PartialMethod("Class B Method");
}
partial void PartialMethod(string text);
}
partial class B
{
partial void PartialMethod(string text)
{
Console.WriteLine(text);
}
}
■ C# 4.0 での新機能
・dynamic 型
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/reference-types#the-dynamic-type
dynamic 型はコンパイル時の型チェックを行わず、実行時に解決される。
try
{
dynamic a = 1;
Console.WriteLine(a);
Console.WriteLine(a.GetType().Name);
a = a + 1;
Console.WriteLine(a);
a = "text";
a = a + 1;
Console.WriteLine(a);
Console.WriteLine(a.GetType().Name);
Console.WriteLine(a.ToString());
Console.WriteLine(a.ToString2());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
・省略可能な引数 (オプション引数)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments
メソッドなどのパラメーターに規定値を設定し、省略可能にできる。
static void Main(string[] args)
{
AddAndWriteLine(10, 20, "計算結果 => {0}");
AddAndWriteLine(10, 20);
AddAndWriteLine(1);
}
static int AddAndWriteLine(int a, int b=2, string format="結果は {0} です.")
{
var c = a + b;
Console.WriteLine(string.Format(format, c));
return c;
}
・名前付き引数
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments
メソッドなどを呼び出す際、パラメーターを名前付きで記述できる。名前付きで記述した場合、パラメーターを任意の順に指定することも可能。
static void Main(string[] args)
{
AddAndWriteLine(10, 20, "計算結果 => {0}");
AddAndWriteLine(10, format: "計算結果 => {0}", b: 20);
AddAndWriteLine(10, format: "計算結果 => {0}");
AddAndWriteLine(10, 20, format: "計算結果 => {0}");
static int AddAndWriteLine(int a, int b = 2, string format = "結果は {0} です.")
{
var c = a + b;
Console.WriteLine(string.Format(format, c));
return c;
}
・ジェネリックの共変性と反変性
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/in-generic-modifier
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/out-generic-modifier
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/covariance-contravariance/variance-in-generic-interfaces
共変性により、ジェネリック型の変数に型パラメータがサブクラスにであるオブジェクトを代入できる。 反変性によりジェネリック型の変数に型パラメータがスーパークラスにであるオブジェクトを代入できる。
class Program
{
static void Main(string[] args)
{
IA<string> a = new A<object>();
a.Set("text");
IB<object> b = new B<string>();
object o = b.Get();
}
}
interface IA<in T>
{
void Set(T t);
}
class A<T> : IA<T>
{
public void Set(T t) { ; }
}
interface IB<out T>
{
T Get();
}
class B<T> : IB<T>
{
private T _t;
public void Set(T t) { _t = t; }
public T Get() { return _t; }
}
■ C# 5.0 での新機能
・非同期処理 (async/await)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/async/
同期メソッドの作成とほぼ同様の容易さで、非同期メソッドを作成できる。async が付いたメソッドは非同期メソッドになる。非同期メソッドの完了を待機する場合は await をつけてメソッドを呼び出す。
static void Main(string[] args)
{
Method();
MethodAsync().Wait();
Console.ReadKey();
}
static async Task<string> MethodAsync()
{
var client = new System.Net.Http.HttpClient();
var html = await client.GetStringAsync("http://rksoftware.hatenablog.com/");
Console.WriteLine(html.Take(100).ToArray());
return html;
}
static void Method()
{
var client = new System.Net.WebClient();
client.DownloadStringCompleted +=
(object sender, System.Net.DownloadStringCompletedEventArgs e) =>
{
Console.WriteLine(new string(e.Result.Take(100).ToArray()));
};
client.DownloadStringAsync(new Uri("http://rksoftware.hatenablog.com/"));
}
・呼び出し元情報の属性 (CallerMemberName など)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/caller-information
メソッドの呼び出し元の情報を省略可能な引数として取得できる。メソッドを呼び出す際に引数を省略すると、呼び出し元のメソッド名などが設定される。
つまり、呼び出されたメソッド側で呼び出したメソッドの情報を知ることができる。
static void Main(string[] args)
{
MyMethod();
MyProperty = 10;
}
static void WriteTrace(string message,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
Console.WriteLine(string.Format("message: {0}", message));
Console.WriteLine(string.Format("member name: {0}", memberName));
Console.WriteLine(string.Format("source file path: {0}", sourceFilePath));
Console.WriteLine(string.Format("source line number: {0}", sourceLineNumber));
}
static void WritePropertyChanged(object oldValue,
object newValue,
[System.Runtime.CompilerServices.CallerMemberName] string name = "")
{
Console.WriteLine(string.Format("{0} changed: {1} -> {2}", name, oldValue, newValue));
}
static void MyMethod()
{
WriteTrace("message");
}
private static int _myProperty;
static int MyProperty {
get { return _myProperty; }
set { WritePropertyChanged(_myProperty, value); _myProperty = value; }
}
■ C# 6.0 での新機能
・文字列補間
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/interpolated-strings
含まれる挿入式をその文字列表現に置き換えた文字列を返す。
string firstName = "埼玉";
string lastName = "太郎";
Console.WriteLine($"{firstName} {lastName}");
・自動実装プロパティ get アクセサーのみの宣言
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
get アクセサーのみを宣言し、変更できないプロパティの作成できる。
class Program
{
static void Main(string[] args)
{
MyClass c = new MyClass();
int i = c.MyProperty;
}
}
class MyClass
{
internal int MyProperty { get; }
public MyClass()
{
MyProperty = 10;
}
}
・自動実装プロパティの初期化
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties
フィールドと同様に自動実装プロパティを初期化することができる。
static void Main(string[] args)
{
int i = MyProperty;
Console.WriteLine(i);
}
static int MyProperty { get; set; } = 10;
・式形式のメンバー
https://docs.microsoft.com/ja-jp/dotnet/csharp/methods#expr
メソッドの本文が 1 つのステートメントの場合、=> を使用した構文ショートカットが使用できる。
static void Main(string[] args)
{
MyClass c = new MyClass();
c.FirstName = "埼玉";
c.LastName = "太郎";
Console.WriteLine(c.ToString());
Console.ReadKey();
}
class MyClass
{
internal string FirstName { get; set; }
internal string LastName { get; set; }
public override string ToString() => $"{FirstName} {LastName}";
}
・get アクセサーのみの自動実装プロパティ を式本体の定義
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/properties
読み取り専用プロパティの場合に get アクセサーを式形式のメンバーとして実装できる。
static void Main(string[] args)
{
FirstName = "埼玉";
LastName = "太郎";
Console.WriteLine(FullName);
}
static string FirstName { get; set; }
static string LastName { get; set; }
static string FullName => $"{FirstName} {LastName}";
・using static ディレクティブ
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-static
static メソッドなどへアクセスする際、名前空間と同様に型名も指定せずに使用できる using の記述ができる。
using System;
using System.Threading.Tasks;
using static System.Math;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Math.PI);
Console.WriteLine(PI);
}
}
}
・Null 条件演算子
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/null-conditional-operators
メンバー アクセスおよびインデックス操作のチェーンの 1 つの演算が null を返す場合、チェーンの実行の残りの部分を停止し null を返すショートサーキット。
string s = "text";
Console.WriteLine(s.Length.ToString());
Console.WriteLine(s.ToCharArray()[0]);
s = null;
try
{
Console.WriteLine(s.Length.ToString());
Console.WriteLine(s.ToCharArray()[0]);
}
catch (NullReferenceException ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine(s?.Length.ToString() == null);
Console.WriteLine(s?.ToCharArray()?[0] == null);
・nameof 式
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/nameof
変数、型、またはメンバーの名前を文字列として取得できる。
class Program
{
static void Main(string[] args)
{
int variable;
Console.WriteLine(nameof(Program));
Console.WriteLine(nameof(variable));
Console.WriteLine(nameof(MyMethod));
Console.WriteLine(nameof(MyProperty));
}
static void MyMethod() { ; }
static int MyProperty { get; set; }
}
・例外をフィルター処理する述語式 (when)
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/try-catch
処理対象の例外をフィルターする際に、例外オブジェクトの型の評価に続いて、述語式を使用して例外をフィルターできる。
static void Main(string[] args)
{
MethodA(null, "text");
MethodA("text", null);
}
static void MethodA(string text1, string text2)
{
try
{
MethodB(text1, text2);
}
catch (ArgumentException ex) when (ex.ParamName == "text1")
{
Console.WriteLine($"{nameof(text1)}:{ex.Message}");
}
catch (ArgumentException ex) when (ex.ParamName == "text2")
{
Console.WriteLine($"{nameof(text2)}:{ex.Message}");
}
}
static void MethodB(string text1, string text2)
{
if (string.IsNullOrEmpty(text1)) throw new ArgumentException("Null または Empty です", nameof(text1));
if (string.IsNullOrEmpty(text2)) throw new ArgumentException("Null または Empty です", nameof(text2));
}
・catch/finally ブロック内での await
該当のドキュメントが見つかりませんでした。
catch および finally ブロックで await による非同期処理ができる。
static void Main(string[] args)
{
MethodAsync().Wait();
}
static async Task<string> MethodAsync()
{
var client = new System.Net.Http.HttpClient();
var html = await client.GetStringAsync("http://rksoftware.hatenablog.com/about");
try
{
html = html.Substring(0, int.MaxValue);
}
catch(ArgumentOutOfRangeException ex)
{
Console.WriteLine(ex.Message);
html = await client.GetStringAsync("http://rksoftware.hatenablog.com/about");
html = new string(html.Take(100).ToArray());
}
Console.WriteLine(html);
return html;
}
・インデックス初期化 (Dictionary 初期化)
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers
単純なコレクションだけでなく、コレクションがインデックスでの値の読み書きができる場合、インデックス指定で初期化できる。
List<string> list = new List<string>
{
"saitama",
"gunma",
"ibaraki"
};
Dictionary<int, string> dictionary = new Dictionary<int, string>
{
[101] = "saitama",
[201] = "gunma",
[301] = "ibaraki"
};
Console.WriteLine(list[0]);
Console.WriteLine(dictionary[201]);
・拡張メソッドでコレクション初期化子
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/object-and-collection-initializers#collection-initializers
Add メソッドが拡張メソッドで定義されている型も、初期化子を指定できる。
class Program
{
static void Main(string[] args)
{
MyClass c = new MyClass() { "saitama", "gunma", "ibaraki" };
Console.WriteLine(c);
}
}
static class MyClassExtension
{
internal static void Add(this MyClass c, string text)
{
c.Push(text);
}
}
class MyClass: IEnumerable<string>
{
private List<string> _texts = new List<string>();
internal void Push(string text) { _texts.Add(text); }
public override string ToString() { return string.Join(", ", _texts); }
public IEnumerator<string> GetEnumerator() { return _texts.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return _texts.GetEnumerator(); }
}
・オーバーロードの解決の改善
[ 良いリンクを見つけられませんでした ]
オーバーロードで引数に Action を受け取るメソッドと Func を受け取るメソッドがある場合のコンパイラによる選択が改善した。
static void Main(string[] args)
{
Task.Run(() => DoMethod());
Task.Run(DoMethod);
}
static Task DoMethod()
{
Console.WriteLine("DoMethod");
return Task.FromResult(0);
}
■ 出典/参考文献
上記まとめの作成に、次のサイトを大いに参考にさせていただきました。
文言やサンプルコードは C# のガイド のコードを利用させていただきました。
C# のガイド | Microsoft Docs
C# によるプログラミング入門 | ++C++; // 未確認飛行 C