In C# 5 war die Abschluss-Semantik der foreach
-Anweisung (wenn die Iterationsvariable von anonymen Funktionen "erfasst" oder "geschlossen" wurde) famously changed (link to thread on that topic).Closure-Semantik für foreach over Arrays von Zeigertypen
Frage: War es die Absicht, dies für Arrays von Zeigertypen auch zu ändern?
Der Grund, warum ich frage ist, dass die „Erweiterung“ eine foreach
Anweisung neu geschrieben werden muss, aus technischen Gründen (wir nicht die Current
Eigenschaft der System.Collections.IEnumerator
verwenden können, da diese Eigenschaft Typ deklariert hat object
, die mit einem Zeiger nicht kompatibel ist Typ) im Vergleich zu foreach
gegenüber anderen Sammlungen. Der entsprechende Abschnitt in der C# Language Specification, "Pointer-Arrays", in Version 5.0, sagt, dass:
foreach (V v in x) EMBEDDED-STATEMENT
zu erweitert wird:
{
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
}
}
Wir nehmen zur Kenntnis, dass die Erklärung V v;
ist außerhalb aller for
Schleifen. So scheint es, dass die Closing-Semantik immer noch der "alte" C# 4-Flavor ist, "Loop-Variable wird wiederverwendet, Loop-Variable ist" äußerlich "in Bezug auf die Schleife".
Um deutlich zu machen, was ich rede, halte das komplette C# 5-Programm:
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.
}
Also, was die korrekte Ausgabe des obigen Programms ist?
Anmerkung: Die obige Expansion hat ein weiteres offensichtliches Problem, dass es schreibt 'a.GetValue (i0, i1, ..., iN)' 'wo GetValue' scheint die Methode' System definiert werden .Array'. Aber diese Methode hat den Rückgabewert 'object' und kann daher nicht für Zeigertypen verwendet werden. Daher ist die C# -Spezifikation nicht in der Lage, _ "jeden Versuch zu vermeiden, auf die Array-Elemente über' System.Array' "_ zuzugreifen, um die C# -Spezifikation selbst zu zitieren. Vielleicht hätte das "a [i0, i1, ..., iN]" sein sollen, wobei die Klammer '[...]' durch den Unterabschnitt _ "Array element access" _ definiert wird. Versuchen Sie im obigen Codebeispiel "arrayOfPointers.GetValue (0)" selbst zu sagen. –