C#5では、foreach
ステートメントのクロージャセマンティクス(匿名関数によって反復変数が "キャプチャ"または "クローズオーバー"されたとき)はfamously changed (link to thread on that topic)でした。ポインタ型のforeachオーバーレイのクロージャセマンティクス
質問:ポインタ型の配列に対してもこれを変更するつもりでしたか?
私たちは、このプロパティは、ポインタと互換性のないタイプobject
宣言しているので、System.Collections.IEnumerator
のCurrent
プロパティを使用することはできません(foreach
文の「拡大」は技術的な理由のために、書き直さなければならないことである尋ねる理由他のコレクションに比べてforeach
と比較して、私たちは、宣言V v;
があることに注意して
{
T[,,…,] a = x;
V v;
for (int i0 = a.GetLowerBound(0); i0 <= a.GetUpperBound(0); i0++)
for (int i1 = a.GetLowerBound(1); i1 <= a.GetUpperBound(1); i1++)
…
for (int in = a.GetLowerBound(N); iN <= a.GetUpperBound(n); iN++) {
v = (V)a.GetValue(i0,i1,…,iN);
EMBEDDED-STATEMENT
}
}
:
foreach (V v in x) EMBEDDED-STATEMENT
がに展開されます。バージョンではC#言語仕様の該当するセクション、"ポインタ配列"は、5.0、と述べていますfor
ループの外側にあります。したがって、クロージャのセマンティクスは "古い" C#4のフレーバーであると思われます。 "ループ変数は再利用され、ループ変数はループに対して"外側 "です。
、私が何を言っているか、それを明確に、この完全なC#5のプログラムを検討する:
using System;
using System.Collections.Generic;
static class Program
{
unsafe static void Main()
{
char* zeroCharPointer = null;
char*[] arrayOfPointers =
{ zeroCharPointer, zeroCharPointer + 1, zeroCharPointer + 2, zeroCharPointer + 100, };
var list = new List<Action>();
// foreach through pointer array, capture each foreach variable 'pointer' in a lambda
foreach (var pointer in arrayOfPointers)
list.Add(() => Console.WriteLine("Pointer address is {0:X2}.", (long)pointer));
Console.WriteLine("List complete");
// invoke those delegates
foreach (var act in list)
act();
}
// Possible output:
//
// List complete
// Pointer address is 00.
// Pointer address is 02.
// Pointer address is 04.
// Pointer address is C8.
//
// Or:
//
// List complete
// Pointer address is C8.
// Pointer address is C8.
// Pointer address is C8.
// Pointer address is C8.
}
したがって、上記のプログラムの正しい出力は何ですか?
備考:上記の拡張は、それは 'a.GetValue(I0、I1、...、IN)が' 'どこGetValue'は、システムの'によって定義された方法であると思わ書き込むには、別の明らかな問題があります.Array'。しかし、そのメソッドは戻り値 'object'を持っているので、ポインタ型には使用できません。したがって、C#仕様は、 "System.Array" _を介して配列要素にアクセスしようとすると、C#仕様自体を引用することはできませんでした。おそらく 'a [i0、i1、...、iN]'だったはずです。ここで、ブラケット '[...]'はサブセクション_ "配列要素アクセス" _によって定義されています。上記のコードサンプルでは、 'arrayOfPointers.GetValue(0)'と言ってみてください。 –