Gibt es eine Möglichkeit, die Inline-Optimierung von Eigenschaften in C # zu vermeiden?

7

Ich habe also eine PropertyBag-Klasse, die INotifyPropertyChanged implementieren soll. Um diesen Code so sauber wie möglich zu machen und Benutzerfehler zu vermeiden, verwende ich den Stack, um den Namen der Eigenschaft zu erhalten. Sehen Sie, wenn der Name der Eigenschaft nicht exakt mit der tatsächlichen Eigenschaft übereinstimmt, dann haben Sie einen Fehler und ich versuche, mich davor zu schützen.

Also, hier ist ein Beispiel für die Verwendung der Klasse:

%Vor%

Der wichtige Code für die Basis-PropertyBag ist hier:

%Vor%

Nun, da Sie meinen Code gesehen haben, kann ich Ihnen das Problem sagen ... In einigen Fällen wurde unter Release Build der "Foo" Setter im "MyData" -Konstruktor für Inline als SetProperty optimiert (- 1). Leider scheitert diese Inline-Optimierung an meiner SetProperty-Methode, weil ich sie nicht mehr von einer Eigenschaft aus anrufe! SCHEITERN. Es scheint, dass ich mich auf diese Weise nicht auf den StackTrace verlassen kann.

Kann jemand A: Finden Sie einen besseren Weg, dies zu tun, aber vermeiden Sie immer noch "Foo" zu GetProperty und SetProperty? B: Finden Sie heraus, wie der Compiler in diesem Fall nicht optimieren soll?

    
Brian Genisio 17.02.2009, 16:32
quelle

5 Antworten

13

Hier ist der Stack langsam und unnötig; Ich würde einfach verwenden:

%Vor%

(Hinweis: Ich habe viel mit benutzerdefinierten Eigenschaftsmodellen gearbeitet; ich weiß, dass das gut funktioniert ...)

Eine andere Alternative ist ein Objektschlüssel (Referenzvergleich zum Vergleichen verwenden) - viele ComponentModel funktionieren auf diese Weise, wie auch einige der Eigenschaften in WF / WPF:

%Vor%

Natürlich könnten Sie einen Typ für die Schlüssel deklarieren (mit einer Name -Eigenschaft) und folgendes verwenden:

%Vor%

usw .; Um jedoch die Frage zu beantworten: Markieren Sie es (aber nicht dies tun) mit:

%Vor%

oder

%Vor%

oder

%Vor%

    
Marc Gravell 17.02.2009, 16:38
quelle
2

Die Verwendung des Stapels ist keine gute Idee. Sie verlassen sich auf die interne Implementierung des Compilers, um Ihren Eigenschaftenbeutel mit den Spracheigenschaften künstlich zu verknüpfen.

  1. mit der Anforderung, das Attribut MethodImpl hinzuzufügen, macht die Verwendung Ihres Eigentumsbeutels für andere Entwickler nicht transparent.
  2. selbst wenn die Eigenschaftstasche das Attribut MethodImpl hat, garantiert nichts, dass es das erste Bild auf dem Aufrufstapel ist. Es ist möglich, dass die Assembly instrumentiert oder modifiziert wurde, um Anrufe zwischen der tatsächlichen Eigenschaft und dem Anruf in Ihre Eigentumstasche einzufügen. (Think Aspect Programmierung)
  3. Neue Sprachen oder sogar eine zukünftige Version des C # -Compilers könnten die Eigenschaften-Accessoren anders verzieren als '_get' und '_set'
  4. Das Konstruieren des Aufruf-Stacks ist ein relativ langsamer Vorgang, da der interne komprimierte Stack dekomprimiert werden muss und der Name jedes Typs und jeder Methode durch Reflektion erhalten werden muss.

Sie sollten wirklich Ihre Property-Bag-Accessoren implementieren, um einen Parameter zur Identifizierung der Eigenschaft zu verwenden - entweder einen String-Namen (wie Hastable) oder ein Objekt (wie die WPF-Abhängigkeits-Eigenschaft bag)

    
Franci Penov 17.02.2009 16:57
quelle
2

Probieren Sie das neue [CallerMemberName] -Attribut aus.

Platzieren Sie es auf einen Parameter zu Ihrer Methode ([CallerMemberName] callerName = null) und der Compiler überschreibt alle Aufrufe Ihrer Methode, um den Namen des Aufrufers automatisch zu übergeben (Ihre Aufrufe übergeben den Parameter überhaupt nicht).

Es beseitigt keine Optimierungen und ist viel schneller als Lambdas oder Reflektion oder Stacks und arbeitet im Release-Modus.

P.S. Wenn CallerMemberNameAttribute in Ihrer Version des Frameworks nicht vorhanden ist, definieren Sie es einfach (leer). Es ist ein Sprachfeature, kein Framework-Feature. Wenn der Compiler [CallerMemberNameAttribute] für einen Parameter sieht, funktioniert es einfach.

    
Chris Bordeman 28.07.2014 23:20
quelle
1

Sie können versuchen, eine T4-Vorlagendatei zu erstellen, damit Ihre Eigenschaften automatisch mit den richtigen Eigenschaftsnamen für die Methoden GetProperty () und SetProperty () generiert werden können.

T4: Text Template Transformation Toolkit T4-Codegenerierung (Text Template Transformation Toolkit) - Bestgehütetes Visual Studio-Geheimnis

    
Jozef Izso 17.02.2009 17:44
quelle
1

Wenn Sie hartcodierte Zeichenfolgen vermeiden möchten, können Sie Folgendes verwenden:

%Vor%

Fügen Sie weitere Sicherheitsüberprüfungen hinzu, so wie Sie es für richtig halten

dann wird die Eigenschaft

%Vor%

Sätze ändern sich auf die gleiche Weise.

GetCurrentMethod () durchläuft auch den Stack, tut dies jedoch über einen (internen) nicht verwalteten Aufruf, der auf Stack-Markern basiert, so dass er auch im Release-Modus funktioniert.

Alternativ für eine schnelle Korrektur [MethodImpl] mit MethodImplAttributes.NoOptimization) oder MethodImplAttributes.NoInlining funktioniert auch, wenn auch mit einem Performance-Hit (obwohl Sie den Stack-Frame jedes Mal durchlaufen, wenn dieser Treffer vernachlässigbar ist).

Eine weitere Technik, um eine gewisse Kompilierzeitprüfung durchzuführen, ist:

%Vor%

wobei Xxxxx die Klasse ist, in der die Eigenschaft definiert ist. Wenn die statische Natur Probleme verursacht (Threading oder sonstwie ist es möglich, einen Instanzwert zu erstellen).

Ich sollte darauf hinweisen, dass diese Techniken wirklich aus Interessensgründen sind, ich behaupte nicht, dass es sich um gute allgemeine Techniken handelt.

    
ShuggyCoUk 17.02.2009 16:56
quelle

Tags und Links