Er det mulig å passere egenskaper som "ut" eller "ref" parametere?

stemmer
26

Kan jeg passerer en egenskap som en ut eller ref parameter hvis ikke så hvorfor ikke?

f.eks

Person p = new Person(); 

. . .

public void Test(out p.Name);
Publisert på 19/02/2009 klokken 09:43
kilden bruker
På andre språk...                            


4 svar

stemmer
36

Unnskyldninger for det korte svaret, men nei, C # språkspesifikasjonen forbyr det.

Se dette svaret til et annet spørsmål for å se hva som skjer når du prøver. Det sier også at du ikke bør gjøre eiendommen bare være en offentlig felt for å komme seg rundt restriksjonen.

Håper dette hjelper

EDIT: Du spør hvorfor?

Du passerer en variabel til en outeller refparameter du faktisk passerer adressen (eller plassering i minnet) på variabelen. Inne i funksjon kompilatoren vet hvor den variable virkelig er, og blir, og skriver verdier til denne adressen.

En eiendom ser ut som en verdi, buts det er faktisk et par funksjoner, hver med en annen signatur. Så for å passere en eiendom, vil du faktisk trenger å passere to funksjonspekere, en for få, og en for settet.

Dvs en helt annen ting å passere til en funksjon enn adressen til en variabel

dvs. en variabel adresse v to funksjonspekere.

Oppdatering
Hvorfor ikke C # bare se etter dette for oss?

Jeg er ingen Eric Lippert , men jeg vil ha en gå på hvorfor

Hva bør signaturen til funksjonen du ringer være?
La oss si du vil kalle void MyFn(ref int i)bør det forbli slik, eller bør det endre å si at vi også tillate egenskaper? Hvis den endres til noen syntaks som void MyFn(prop_ref int i)så dette er ganske ubrukelig, kan du ikke passere eiendommer til bibliotekfunksjoner eller tredje part kode som ikke ble skrevet med den spesielle prop_ref modifier. Uansett tror jeg du antyder det bør ikke være annerledes.

Nå kan si MyFnpass itil en COM-funksjon, eller WinAPI samtale, passerer adressen i(dvs. utenfor .net, med ref). Hvis det er en eiendom, hvordan får du adressen i? Det kan være noen reell int under eiendommen for å få adressen. Gjør du det VB.Net gjør?

De Vb.net kompilator flekker når en egenskap føres som en ByRef argument til en metode. På det tidspunktet erklærer det en variabel, kopierer eiendom til variabel, passerer den variable ByRef og deretter etter metoden kalles, kopier den variable tilbake til eiendommen. dvs

MyFunc(myObject.IntProperty)

blir

Dim temp_i As Integer = myObject.IntProperty
MyFunc(temp_i)
myObject.IntProperty = temp_i

Eventuelle eiendom bivirkninger ikke skje før MyFuncavkastning, noe som kan føre til alle slags problemer og føre til svært subtile bugs.

I min ydmyke mening Vb.Net løsning på dette problemet er også ødelagt, så jeg kommer ikke til å akseptere det som et svar.

Hvordan tror du det C # kompilatoren skal håndtere dette?

Svarte 19/02/2009 kl. 09:45
kilden bruker

stemmer
0

I stedet bør du gjøre noe som dette

WhatEverTheType name;

Test(out name);

// Choose one of the following construction

Person p = new Person();
p.Name = name;

Person p = new Person(name);
Person p = new Person(Name => name);
Svarte 19/02/2009 kl. 10:43
kilden bruker

stemmer
11

Andre har forklart at du ikke kan gjøre dette i C #. I VB.NET, du kan gjøre dette, selv med opsjon streng / eksplisitt på:

Option Strict On
Option Explicit On
Imports System.Text

Module Test

   Sub Main()
       Dim sb as new StringBuilder
       Foo (sb.Length)
   End Sub

   Sub Foo(ByRef x as Integer)
   End Sub

End Module

Koden ovenfor tilsvarer dette C # -kode:

using System.Text;

class Test
{
     static void Main()
     {
         StringBuilder sb = new StringBuilder();
         int tmp = sb.Length;
         Foo(ref tmp);
         sb.Length = tmp;
     }

     static void Foo(ref int x)
     {
     }
}

Personlig er jeg glad for at C # ikke har dette - det er muddying vannet ganske mye, spesielt i forhold til verdien av eiendommen dersom parameteren er satt i metoden, men da et unntak.

EDIT: Som forespurt, mitt resonnement for hvorfor jeg tror passerer eiendommer i Muddies vannet. Hvis du passerer en normal variabel som referanse, da den variabelen evalueres hver gang det er referert i metoden. Dersom verdien endres av en eller annen grunn (for eksempel som en sideeffekt av noe annet arbeid i metoden) så at endringen blir straks synlig i fremgangsmåten. Det er ikke tilfelle hvis du passerer en eiendom ved referanse i VB.NET: eiendommen getter startes en gang, og da eiendommen setter startes en gang. Det er ikke som du passerer "her er en egenskap - få og sette fra at når du bruker parameteren."

Her er en komplett eksempel der passerer et felt og passerer en helt trivielt eiendom i .NET har svært ulike resultater:

Option Strict On
Option Explicit On
Imports System.Text

Class Test

   Dim counter as Integer

   Property CounterProperty As Integer
       Get
           Return counter
       End Get
       Set (ByVal value as Integer)
           counter = value
       End Set
   End Property

   Sub Increment
       counter += 1
   End Sub

   Shared Sub Main()
       Dim t as new Test()
       Console.WriteLine("Counter = {0}", t.counter)
       t.Foo(t.counter)
       Console.WriteLine("Counter = {0}", t.counter)

       t.CounterProperty = 0
       Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
       t.Foo(t.CounterProperty)
       Console.WriteLine("CounterProperty = {0}", t.CounterProperty)
   End Sub

   Sub Foo(ByRef x as Integer)
       x = 5
       Increment
       Increment
       Increment
       x += 1
   End Sub

End Class
Svarte 19/02/2009 kl. 11:09
kilden bruker

stemmer
2

En annen grunn til dette er ikke tillatt fordi dommeren og ut parameter er lesbar og skrivbar inne i en metode, mens en eiendom kan være skrivebeskyttet / writeonly.

Person
{
    public string Name { get { return "me"; } }
}

Hva nå hvis du kan gjøre dette?

Test(out p.Name);    

public void Test(out string name)
{
    name = "someone else";
}

Du er nå ikke deg, men noen andre, men det er mot kontrakten du har gjort med getbare eiendom Name(hvis noen gang dette arbeidet). Dette er det samme tilfelle med skrivebeskyttet medlems felt av klassen, kan du passere sin referanse.

Person
{
    public readonly string name = "me";
}

Test(out p.name); //not possible.

Kan være C#kan komme opp med en skrivebeskyttet / writeonly argumenter for en metode:

public void Test(out settable string name, gettable int count, bool whatever)
{
    name = "someone else";
}

Test(out p.Name, 0, true); // doesnt compile since p.Name is readonly.
Svarte 11/02/2013 kl. 11:00
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more