2010-08-06 17 views

risposta

6

Le proprietà sono [un paio di get e set] metodi con una sintassi carina per invocarli che li fa apparire come campi.

I parametri di uscita possono essere riferimenti a campi o "campi" basati su stack (ad es. Locali).

Il colmare questa lacuna non è generalmente affrontato dalle lingue (e sicuramente non direttamente dal modello CLR e IL). (+1 su @Heinzi per i riferimenti di trucchi VB)

+1

Un apprezzamento per il -1 sarebbe apprezzato (a parte il fatto che la risposta di @Mark Byers è cresciuta fino a incorporare questo angolo dal suo post iniziale?) –

+1

@Craig Johnston: Ti lascio vedere attraverso la nebbia delle risposte e del dibattito la tua domanda apparentemente diretta è stata provocata! –

+0

+1: per farlo correttamente dovresti effettivamente catturare un paio di chiusure per ogni proprietà. A quel punto 'ref int i' nasconderà un codice abbastanza coinvolto. . . ma solo quando viene passata una proprietà. Grande differenza tra de-referenziare un int e carting around e l'utilizzo di coppie di chiusure. Post scriptum Non riesco a sopportare i downvotes senza commenti. –

3

L'argomento passato a un parametro di partenza non può essere una proprietà. Se provate a compilare il vostro codice otterrete un errore di compilazione.

A property, indexer or dynamic member access may not be passed as an out or ref parameter

La ragione è che una proprietà non è realmente campo (potrebbe avere un campo di supporto, ma non potrebbe). Sono due metodi chiamati get_Foo e set_Foo. Vedere c# property and ref parameter, why no sugar? per ulteriori spiegazioni sul perché questo non funziona.

codice di esempio che dà l'errore di compilazione:

class Program 
{ 
    public int Foo { get; set; } 
    public void Bar(out int x) 
    { 
     x = 5; 
    } 
    void Run() 
    { 
     Bar(out Foo); // compile error 
    } 
    static void Main() 
    { 
     new Program().Run(); 
    } 
} 
4

No, non è possibile utilizzare un proprietà come parametro ref o out in C#, dal momento che il CLR non supporta questo. Il passaggio di una variabile di istanza dovrebbe funzionare correttamente.

Come nota laterale, VB.NET consente il passaggio proprietà e utilizza una tecnica chiamata "ricopiare ByRef", come spiegato in this MSDN blog entry.

+2

+1: sconsiglio vivamente di passare le proprietà byref in VB.Net, può avere effetti collaterali sorprendenti, meglio se - come C# - non era supportato. –

+2

@Binary: hai qualche prova/riferimento per questo reclamo? – CJ7

+0

@Craig: ho aggiunto la mia "risposta" qui sotto, con esempi di codice VB che mostrano cosa intendo http://stackoverflow.com/questions/3422078/c-can-out-parameters-in-functions-be-object- proprietà-variabili/3424123 # 3424123 –

0

È possibile utilizzare il parametro out con i campi (o le persone del luogo come già detto).

4

Non è possibile farlo con C#.
È possibile con VB.Net, ma considero questa una cattiva idea. Il seguente codice e l'output mostrano come lo fa e mostra perché penso che sia una cattiva idea, al punto in cui vorrei VB.net, inoltre, non ha permesso questo

Public Class MySimpleClass 
    Private _privateInt As Integer 
    Public PublicInt As Integer 

    Public Property PrivateInt() As Integer 
     Get 
      Return _privateInt 
     End Get 
     Set(ByVal value As Integer) 
      _privateInt = value 
     End Set 
    End Property 

    Public Sub MyNotifier() 
     Console.WriteLine("PublicInt {0} : PrivateInt {1} : Values are not the same", PublicInt, PrivateInt) 
    End Sub 

End Class 

Ora chiamare questo da un sub principale, in questo modo

Sub Main() 
    Dim sampleClass As New MySimpleClass 
    IterateAndUpdate(sampleClass.PrivateInt, sampleClass.PublicInt, AddressOf sampleClass.MyNotifier) 

    Console.WriteLine("Private {0} : Public {0} : values are the same ", sampleClass.PrivateInt, sampleClass.PublicInt) 
    Console.ReadKey() 
End Sub 

Sub IterateAndUpdate(ByRef anInt As Integer, ByRef anOtherInt As Integer, ByVal notifier As Action) 
    For i As Integer = 1 To 9 
     anInt = i 
     anOtherInt = i 
     notifier() 
    Next 
End Sub 

emette

PublicInt 1 : PrivateInt 0 : Values are not the same
PublicInt 2 : PrivateInt 0 : Values are not the same
PublicInt 3 : PrivateInt 0 : Values are not the same
PublicInt 4 : PrivateInt 0 : Values are not the same
PublicInt 5 : PrivateInt 0 : Values are not the same
PublicInt 6 : PrivateInt 0 : Values are not the same
PublicInt 7 : PrivateInt 0 : Values are not the same
PublicInt 8 : PrivateInt 0 : Values are not the same
PublicInt 9 : PrivateInt 0 : Values are not the same
Private 9 : Public 9 : values are the same

si può vedere che il membro PublicInt quando passò ByRef viene aggiornato immediatamente sulla sampleClass, mettere il 012.esposto come una proprietà viene aggiornato solo dopo il termine del metodo IterateAndUpdate.

Pertanto, si ottiene un comportamento nettamente diverso da esattamente la stessa convenzione di chiamata, e dipende da come hai implementato l'oggetto passato (che non è affatto evidente guardando la chiamata a IterateAndUpdate.
La possibilità di nascondere bug, o avere piccole modifiche cambiare il comportamento previsto è sufficiente per me desiderare che questa "caratteristica" non esistesse

A mio parere, questo non funziona correttamente, quindi dovrebbe essere
a) Risolto, che richiederebbe uno sforzo considerevole per il team di compilatori e probabilmente introdurrebbe cambiamenti improvvisi
o
b) Non funziona affatto

+1

+1, analisi interessante. – Heinzi

Problemi correlati