2 Stimmen

C# Compiler und Zwischenspeicherung von lokalen Variablen

EDIT : Ups - wie richtig bemerkt, gäbe es keine Möglichkeit zu wissen, ob der Konstruktor für die betreffende Klasse empfindlich darauf reagiert, wann oder wie oft er aufgerufen wird, oder ob der Zustand des Objekts während der Methode geändert wird, so dass er jedes Mal von Grund auf neu erstellt werden müsste. Ignorieren Sie das Dictionary und betrachten Sie nur die Delegaten, die im Laufe einer Methode in-line erstellt werden :-)


Angenommen, ich habe die folgende Methode mit Dictionary of Type to Action local variable.

void TakeAction(Type type)
{
    // Random types chosen for example.
    var actions = new Dictionary<Type, Action>()
    {
        {typeof(StringBuilder), () =>
            {
                // ..
            }},
         {typeof(DateTime), () =>
            {
                // ..
            }}
    };

    actions[type].Invoke();
}

Das Dictionary wird immer gleich sein, wenn die Methode aufgerufen wird. Kann der C#-Compiler dies bemerken, es nur einmal erstellen und es irgendwo für die Verwendung in zukünftigen Aufrufen der Methode zwischenspeichern? Oder wird es einfach jedes Mal von Grund auf neu erstellt? Ich weiß, es könnte ein Feld der Klasse sein, die es enthält, aber es scheint mir schöner, wenn so etwas in der Methode enthalten ist, die es verwendet.

7voto

OregonGhost Punkte 22841

Woher soll der C#-Compiler wissen, dass es sich jedes Mal um "das gleiche" Wörterbuch handelt? Sie erstellen jedes Mal explizit ein neues Wörterbuch. C# unterstützt keine statischen lokalen Variablen, also müssen Sie ein Feld verwenden. Daran ist nichts auszusetzen, selbst wenn keine andere Methode das Feld verwendet.

Es wäre schlimm, wenn der C#-Compiler so etwas tun würde. Was ist, wenn der Konstruktor der Variablen eine zufällige Eingabe verwendet? :)

7voto

Jon Skeet Punkte 1325502

Kurze Antwort: Nein.

Eine etwas längere Antwort: Ich glaube, es wird das Ergebnis der Erstellung eines Delegaten aus einem Lambda-Ausdruck, der nichts erfasst (einschließlich "this") zwischengespeichert, aber das ist ein ziemlich spezieller Fall.

Der richtige Weg, um Ihren Code zu ändern: deklarieren Sie eine private statische readonly-Variable für das Wörterbuch.

private static readonly Dictionary<Type,Action> Actions = 
    new Dictionary<Type, Action>()
{
    { typeof(StringBuilder), () => ... },
    { typeof(DateTime), () => ... },
}

void TakeAction(Type type)
{
    Actions[type].Invoke();
}

2voto

Lasse V. Karlsen Punkte 364542

Damit ein Compiler dazu in der Lage ist, müsste er in irgendeiner Weise Garantien für die folgenden Punkte bieten:

  • Wenn zwei Objekte auf die gleiche Weise konstruiert werden, entstehen in jeder Hinsicht identische Objekte, abgesehen von ihrer Position im Speicher. Dies würde bedeuten, dass sich das beim zweiten Mal erstellte Objekt nicht vom ersten unterscheidet, im Gegensatz zum Zwischenspeichern eines Objekts vom Typ Random.e
  • Durch die Interaktion mit dem Objekt wird sein Zustand nicht verändert. Dies würde bedeuten, dass die Zwischenspeicherung des Objekts sicher wäre und das Verhalten nachfolgender Aufrufe nicht verändern würde. Dies würde z. B. eine Änderung des Wörterbuchs in irgendeiner Weise ausschließen.

Der Grund dafür ist, dass der Compiler in der Lage sein muss, zu garantieren, dass das Objekt, das er beim ersten Mal konstruiert hat, auch beim nächsten Mal verwendet werden kann, ohne es neu erstellen zu müssen.

Dass C# und .NET keine Mechanismen für diese Garantien haben, ist wahrscheinlich nicht der Grund dafür, dass der Compiler diese Art der Optimierung nicht unterstützt, aber diese müssten erst implementiert werden. Es könnte auch andere solche Garantien geben, die der Compiler haben müsste, bevor er es tun könnte, von denen ich nichts weiß.

Die von Jon Skeet vorgeschlagene Änderung ist im Grunde genommen die Art und Weise, wie man sagt, dass Ich weiß, dass diese beiden Garantien für meinen Code gelten Damit haben Sie die Situation selbst in der Hand.

1voto

Marc Gravell Punkte 970173

Dieses Wörterbuch wird jedes Mal neu erstellt; andernfalls könnten Sie zum Beispiel andere Dinge in das Wörterbuch eingeben, und die Absicht würde verloren gehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X