「C Sharpその他 - C Sharpのバージョン」の版間の差分

ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == ここでは、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]]

案内メニュー