Hoekom kan ek nie 'n eiendom of indekseerder as 'n ref-parameter deurgee wanneer .NET-reflektor wys dat dit in die .NET Framework gedoen is nie?

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

  •  05-07-2019
  •  | 
  •  

Vra

Goed, ek sal knip en plak vanaf .NET reflector om te demonstreer wat ek probeer doen:

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

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

    //More irrelevant code...
}

Hierdie reël kode kom direk uit System.Web.Security.SqlMembershipProvider.UpdateUser (System.Web.dll v2.0.50727) in die .NET Framework.

Die SecUtility.CheckParameter vereis 'n verwysingswaarde as die eerste parameter, waarna hulle 'n eienskap van die gebruiker deurgee wat as die argument ingedien is.

Die definisie van die CheckParameter-kode is:

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

Alles wat dit doen maak sin - op papier ...so ek kry 'n vinnige klein prototipe vir iewers waar ek iets soortgelyks wil gebruik:

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.
    }
}

Hierdie kode sal nie saamstel nie - die fout wys as:

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

Reg genoeg...maar hoekom sal my kode my nie toelaat om iets te doen wat blykbaar in die .NET Framework-kodebasis is nie?Is dit 'n fout met die manier waarop .NET Reflector die DLL interpreteer of is dit 'n fout met die manier waarop ek hul kode interpreteer?

Was dit nuttig?

Oplossing

Ek dink dit is 'n slegte interpretasie van Reflector.Eintlik as jy jou kode soos volg skryf:

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

en stel dit saam in vrystellingsmodus, jy sal dit in Reflector sien:

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

Onthou dat die C#-samesteller nie C#-kode produseer nie, maar IL, so wat jy in Reflector sien is nie altyd die realiteit nie.So om duidelik te verstaan ​​wat onder die enjinkap aangaan, kan jy kyk na die regte kode wat deur die samesteller vervaardig is:

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)

Dit is duidelik dat 'n plaaslike veranderlike gebruik word.

Ander wenke

Dit is 'n weerkaatser fout. Dit is nie regtig verby die eiendom deur verwysing.

Hier is 'n paar C # kode wat dit sal kan weergee.

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 toon hierdie kode vir Foo:

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

Nie net is hierdie ongeldig C #, maar dit is misleidend - dit wil voorstel dat veranderinge aan x binne Bar sou een of ander manier p.Name verander -. Waar dit is nie die geval as jy kyk na die oorspronklike C # kode

In jou oorspronklike monster, dit maak nog minder sin as UserName is 'n lees-alleen eiendom!

Jy kan probeer om die waarde van die eiendom aan 'n veranderlike voor om dit na die funksie.

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

Dit is nie die mees elegante oplossing, maar dit moet jy wys in die regte rigting. Soos Yuriy gesê in sy kommentaar hierbo, sy waarskynlik iets te doen met die feit dat jy nie uitdruklik verklaar 'n get en stel vir die eiendom.

As jy 'n veranderlike te slaag as 'n ref of uit, die oproep wys eintlik om die geheue waar dit oorspronklik is geleë. So as jy toegelaat word om die eiendom as 'n verwysing te slaag, beteken dit dat jy maak die klas lid teenstrydig. Dit is die rede agter hierdie probleem.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top