it-swarm.com.de

Direkte Array-Initialisierung mit konstantem Wert

Wann immer Sie ein neues Array in C # zuweisen, 

new T[length]

die Array-Einträge werden auf den Standardwert T gesetzt. Das ist null für den Fall, dass T ein Referenztyp oder das Ergebnis des Standardkonstruktors von T ist, wenn T ein Werttyp ist.

In meinem Fall möchte ich ein Int32-Array mit dem Wert -1 initialisieren:

var myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { myArray[i] = -1; }

Nachdem der Speicher für das Array reserviert ist, durchläuft die CLR den neu zugewiesenen Speicher und setzt alle Einträge auf default (int) = 0. Danach setzt mein Code alle Einträge auf -1. 

Das macht die Initialisierung überflüssig. Erkennt das JIT dies und vernachlässigt die Initialisierung auf 0, und wenn nicht, gibt es eine Möglichkeit, einen Teil des Speichers mit einem benutzerdefinierten Wert direkt zu initialisieren?

In Bezug auf C # -Array-Initialisierung - mit nicht voreingestelltem Wert ist die Verwendung von Enumerable.Repeat(value, length).ToArray() keine Option, da Enumerable.ToArray ein neues Array zuordnet und die Werte danach in dieses Feld kopiert.

45
Rauhotz

Es ist nicht überflüssig.

Angenommen, eine Ausnahme wird während Ihrer Initialisierungsschleife ausgelöst. Wenn die CLR den Speicher nicht zuerst gelöscht hat, können Sie möglicherweise den ursprünglichen, nicht initialisierten Speicher "sehen". Dies ist insbesondere aus Sicherheitsgründen eine sehr schlechte Idee. Deshalb garantiert die CLR, dass neu zugewiesener Speicher mit einem 0-Bit-Muster gelöscht wird.

Dasselbe Argument gilt übrigens für Felder in einem Objekt.

Ich vermute, in beiden Fällen könnte die CLR überprüfen, dass Sie das Array vor der Initialisierung nicht an anderer Stelle sichtbar machen. Es ist jedoch eine komplizierte Prüfung, um ein ziemlich einfaches "Löschen dieses Speicherbereichs" zu vermeiden.

33
Jon Skeet

Ähnlich wie Dans Antwort, aber ohne die Verwendung von Sammlungen:

int[] myArray = Enumerable.Repeat(-1, 100).ToArray();
30
Taylor Leese

Wenn Sie in Arrays kaufen, die als schädlich gelten , dann wäre Ihre Frage irritiert, als würden Sie schreiben:

var myArray = new List<int>(Enumerable.Repeat(-1, 100));
10
Ðаn

Ich bezweifle stark, dass die JIT die Standardeinstellung für dieses Szenario wegoptimiert. Der Grund ist, dass dies ein beobachtbarer Unterschied wäre. Betrachten Sie das folgende leicht veränderte Szenario.

obj.myArray = new int[100];
for (int i=0; i<myArray.Length; i++) { obj.myArray[i] = -1; }

Es ist durchaus möglich, dass die Schleife geworfen wird. Zumindest kann die JIT wahrscheinlich nicht beweisen, dass dies nicht der Fall ist. Wenn es geworfen wurde und die CLR den Speicher nicht standardmäßig initialisiert hat, ist das Ergebnis zu beobachten, wenn Sie noch einen Verweis auf obj hätten. 

3
JaredPar

Ich empfehle die Verwendung von Array.Fill als sehr schnelle Möglichkeit, ein Array mit einem Anfangswert zu füllen:

bool[] isPrime = new bool[MaxNum];
Array.Fill(isPrime, true);

Dadurch werden alle Werte im isPrime-Array auf true initialisiert.

0
Martin Zikmund