Warum nicht passieren kann ich eine Eigenschaft oder Indexer als ref Parameter, wenn .NET Reflektor zeigt, dass es in .NET Framework fertig ist?

StackOverflow https://stackoverflow.com/questions/1810785

  •  05-07-2019
  •  | 
  •  

Frage

Okay, ich werde Ausschneiden und Einfügen von .NET Reflektor zu zeigen, was ich versuche zu tun:

public override void UpdateUser(MembershipUser user)
{
    //A bunch of irrelevant code...

    SecUtility.CheckParameter(ref user.UserName, true, true, true, 0x100, "UserName");

    //More irrelevant code...
}

Diese Codezeile kommt direkt aus System.Web.Security.SqlMembershipProvider.UpdateUser (System.Web.dll v2.0.50727) in .NET Framework.

Die SecUtility.CheckParameter erfordert einen Referenzwert als ersten Parameter, auf die sie eine Eigenschaft des Benutzers vorbei sind als Argument übergeben.

Die Definition des CheckParameter Code lautet:

internal static void CheckParameter(ref string param, bool checkForNull, bool checkIfEmpty, bool checkForCommas, int maxSize, string paramName)
{
    //Code omitted for brevity
}

Alles, was er tut macht Sinn - auf dem Papier ... so klopfen ich einen schnellen kleinen Prototyp irgendwo würde ich etwas ähnliches verwenden möchten:

public class DummyClass
{
    public string ClassName{ get; set; }
}

public class Program
{
    private static DoSomething(ref string value)
    {
        //Do something with the value passed in
    }

    public static Main(string[] args)
    {
        DummyClass x = new DummyClass() { ClassName = "Hello World" };

        DoSomething(ref x.ClassName); //This line has a red squiggly underline 
                                      //under x.ClassName indicating the 
                                      //error provided below.
    }
}

Dieser Code wird nicht kompiliert - der Fehler zeigt, wie:

"A property or indexer may not be passed as an out or ref parameter"

Na gut ... aber warum nicht mein Code erlauben Sie mir, etwas zu tun, die in der .NET Framework-Code-Basis zu sein scheinen? Ist das ein Fehler bei der Art und Weise .NET Reflector die DLL interpretiert oder ist dies ein Fehler mit der Art, wie ich ihren Code bin zu interpretieren?

War es hilfreich?

Lösung

Ich denke, es ist eine schlechte Interpretation von Reflector. Eigentlich, wenn Sie schreiben Ihren Code wie folgt:

static void Main(string[] args)
{
    DummyClass x = new DummyClass();
    string username = x.ClassName;
    DoSomething(ref username);
}

und kompilieren Sie es in Release-Modus werden Sie dies in Reflector sehen:

static void Main(string[] args)
{
    DummyClass x = new DummyClass();
    DoSomething(ref x.ClassName);
}

Beachten Sie, dass der C # -Compiler erzeugt C # -Code nicht aber IL so, was Sie in Reflector sehen, ist nicht immer die Realität. So klar zu verstehen, was unter der Haube wird auf Sie am echten Code aussehen kann durch den Compiler erzeugt:

L_000f: callvirt instance string System.Web.Security.MembershipUser::get_UserName()
L_0014: stloc.0 
L_0015: ldloca.s str
L_0017: ldc.i4.1 
L_0018: ldc.i4.1 
L_0019: ldc.i4.1 
L_001a: ldc.i4 0x100
L_001f: ldstr "UserName"
L_0024: call void System.Web.Util.SecUtility::CheckParameter(string&, bool, bool, bool, int32, string)

Es ist klar, dass eine lokale Variable verwendet wird.

Andere Tipps

Es ist ein Reflektor Bug. Es ist wirklich nicht die Eigenschaft, durch Verweis übergeben.

Hier einig C # -Code, die es wiedergeben wird.

using System;

class Person
{
    public string Name { get; set; }
}

class Test
{
    static void Main(){} // Just make it easier to compile

    static void Foo(Person p)
    {
        string tmp = p.Name;
        Bar(ref tmp);
    }

    static void Bar(ref string x)
    {
    }
}

Reflector zeigt den Code für Foo:

private static void Foo(Person p)
{
    Bar(ref p.Name);
}

ist nicht nur diese ungültig C #, aber es ist irreführend - es würde vorschlagen, dass Änderungen innerhalb x irgendwie Bar ändern würde p.Name gemacht -., Wo das nicht der Fall ist, wenn man an dem ursprünglichen C # -Code aussieht

In Ihrer ursprünglichen Probe, es macht noch weniger Sinn als UserName eine schreibgeschützte Eigenschaft ist!

Versuchen Sie, den Wert der Immobilie zu einem variablen Einstellung, bevor es an die Funktion übergeben.

string myClassName = x.ClassName
DoSomething(ref myClassName);

Es ist nicht die eleganteste Lösung, aber es sollte Sie in die richtige Richtung weisen. Wie Yuriy oben in seinem Kommentar sagte, etwas sein vermutlich mit der Tatsache zu tun, dass Sie nicht explizit ein Get- und Set für die Eigenschaft deklarieren.

Wenn Sie eine Variable als ref übergeben oder zu verkleinern, verweist der Anruf tatsächlich in den Speicher, wo sie ursprünglich befindet. Also, wenn Sie berechtigt sind, die Eigenschaft als Referenz zu übergeben, bedeutet das, Sie die Klasse Mitglied inkonsistent machen. Dies ist der Grund für dieses Problem.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top