13,002
回編集
(ページの作成:「== 概要 == ここでは、C# 4.0以降におけるバージョンごとの新機能について記載する。<br> <br> 下図に、Visual StudioとC#、.NET Framework…」) |
|||
137行目: | 137行目: | ||
*: ただし、COMの<code>get_X(index)</code>を<code>X[index]</code>で参照できるだけであり、C#において、インデックス付きプロパティが定義できるわけではない。 | *: ただし、COMの<code>get_X(index)</code>を<code>X[index]</code>で参照できるだけであり、C#において、インデックス付きプロパティが定義できるわけではない。 | ||
*: また、VB.NETで記述したインデックス付きプロパティは、C#から呼ぶ場合は、<code>get_X(index)</code> / <code>set_X(index, value)</code>という記述をする必要がある。 | *: また、VB.NETで記述したインデックス付きプロパティは、C#から呼ぶ場合は、<code>get_X(index)</code> / <code>set_X(index, value)</code>という記述をする必要がある。 | ||
<br><br> | |||
== C# 5.0の新機能 == | |||
* リリース時期 | |||
*: 2012年8月 | |||
* 同世代技術 | |||
*: Visual Studio 2012 | |||
*: .NET Framework 4.5 | |||
*: Visual Basic 11 | |||
*: Windows Runtime | |||
*: .NET Core Profile(現在の.NET Coreの原型) | |||
* 要約・目玉機能 | |||
*: 非同期処理 | |||
<br> | |||
.NET Framework 4以降、言語機能、ライブラリ、ツールは、拡張という形で小出しにされるようになった。<br> | |||
<br> | |||
==== 非同期処理 ==== | |||
async / awaitキーワードを使用することで、非同期処理を簡潔に記述することができる。<br> | |||
<br> | |||
非同期処理には、処理の内容をシーケンス図やフローチャートに起こすと、同期処理と同じになるものがある。<br> | |||
このような処理に対して、async / awaitを使用することにより、同期処理と同じように非同期処理を記述できる。<br> | |||
<br> | |||
==== Caller Info属性 ==== | |||
C++のFILEやLINEマクロに相当するデバッグ用診断を実現するための機能である。<br> | |||
<br> | |||
以下のように、メソッドの引数に属性を付加することで、コンパイラはメソッドの引数に対して診断情報を渡す。<br> | |||
コンパイル結果には、定数やオプション引数と同様、コンパイル時のリテラル埋め込みになる。(実行時のコストは無い)<br> | |||
<br> | |||
* CallerFilePath | |||
*: 呼び出し元のファイル名 | |||
* CallerLineNumber | |||
*: 呼び出し元の行番号 | |||
* CallerMemberName | |||
*: 呼び出し元のメンバ名(メソッド名、プロパティ名、イベント名等) | |||
<syntaxhighlight lang="c#"> | |||
public static class Trace | |||
{ | |||
public static void WriteLine(string message, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0, | |||
[CallerMemberName] string member = "") | |||
{ | |||
var s = string.Format("{0}:{1} - {2}: {3}", file, line, member, message); | |||
Console.WriteLine(s); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
イテレータブロックや非同期関数内から呼び出す場合でも、正常にメソッド名を取得できる。<br> | |||
また、匿名関数(ラムダ式や匿名メソッド式)内で呼び出す場合も、匿名関数を記述しているメソッド名が使用される。<br> | |||
(これらの機能は、内部的に別のクラスやメソッドを生成しているが、そのコンパイラ生成名ではなく、元のメソッド名を取得する)<br> | |||
<br> | |||
==== foreach文の仕様変更 ==== | |||
foreach文の仕様が少し変更された。(破壊的変更になるため、既存の構文が動作しない可能性がある)<br> | |||
<br> | |||
C# 4.0までは、foreach文は以下のように展開されていた。<br> | |||
これは、ラムダ式を使用してforeach文のループ変数(以下の例では、x)をキャプチャする時、意図しない動作になる。<br> | |||
<syntaxhighlight lang="c#"> | |||
static void ForeachSample<T>(IEnumerable<T> data) | |||
{ | |||
// 展開前 | |||
foreach(var x in data) | |||
{ | |||
Console.WriteLine(x); | |||
} | |||
// 展開後 | |||
using(var e = data.GetEnumerator()) | |||
{ | |||
T x; | |||
while(e.MoveNext()) | |||
{ | |||
x = e.Current; | |||
Console.WriteLine(x); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// C# 4.0の場合 | |||
var data = new[] {1, 2, 3}; | |||
Action a = null; | |||
foreach(var x in data) | |||
{ | |||
a += () => Console.WriteLine(x); | |||
} | |||
a(); | |||
// 出力 | |||
3 | |||
3 | |||
3 | |||
</syntaxhighlight> | |||
<br> | |||
C# 5.0では、foreach文の展開結果において、ループ変数(以下の例では、x)の位置がwhile文の内部に展開するように変更された。<br> | |||
<syntaxhighlight lang="c#"> | |||
static void ForeachSample<T>(IEnumerable<T> data) | |||
{ | |||
// 展開前 | |||
foreach(var x in data) | |||
{ | |||
Console.WriteLine(x); | |||
} | |||
// 展開後 | |||
using(var e = data.GetEnumerator()) | |||
{ | |||
while(e.MoveNext()) | |||
{ | |||
T x; | |||
x = e.Current; | |||
Console.WriteLine(x); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
これにより、上記のラムダ式の実行結果は、以下のように変更された。<br> | |||
1 | |||
2 | |||
3 | |||
<br> | |||
C# 4.0までの仕様が前述のようになっていたのは、以下のような理由によるものである。<br> | |||
* xとdataの登場順序が変わらないように展開するため。 | |||
* for文のループ変数と挙動を揃えるため。 | |||
<br> | |||
C# 5.0で仕様変更した理由は、ラムダ式の利用が広まり、上記のようなループ変数にてキャプチャの問題があったからである。<br> | |||
<br><br> | <br><br> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:C_Sharp]] | [[カテゴリ:C_Sharp]] |