2010-06-14 8 views
39

Ich habe einen Delegaten, der ein Objekt ändert. Ich übergebe ein Objekt an den Delegaten von einer aufrufenden Methode, jedoch nimmt die aufrufende Methode diese Änderungen nicht auf. Der gleiche Code funktioniert, wenn ich ein List als das Objekt übergebe.Übergeben von Objekten und einer Liste von Objekten durch Verweis in C#

Ich dachte, dass alle Objekte als Referenz übergeben wurden, so dass alle Änderungen in der aufrufenden Methode widergespiegelt werden würden. Ist das korrekt?

Ich kann meinen Code ändern, um ein ref Objekt an den Delegaten zu übergeben. Aber ich frage mich, warum das notwendig ist. Oder ist es?

public class Binder 
{ 
    protected delegate int MyBinder<T>(object reader, T myObject); 

    public void BindIt<T>(object reader, T myObject) 
    { 
     //m_binders is a hashtable of binder objects 
     MyBinder<T> binder = m_binders["test"] as MyBinder<T>; 
     int i = binder(reader, myObject); 
    } 
} 

public class MyObjectBinder 
{ 
    public MyObjectBinder() 
    { 
     m_delegates["test"] = new MyBinder<MyObject>(BindMyObject); 
    } 

    private int BindMyObject(object reader, MyObject obj) 
    { 
     obj = new MyObject 
     { 
      //update properties 
     }; 
     return 1; 
    } 
} 

///calling method in some other class 
public void CallingMethod() 
{ 
    MyObject obj = new MyObject(); 

    MyObjectBinder binder = new MyObjectBinder(); 
    binder.BindIt(myReader, obj); //don't worry about myReader 

    //obj should show reflected changes 
} 

Update:

ich jetzt Objekte von ref an den Delegaten vorbei als ich ein neues Objekt in BindMyObject bin Instanziierung.

protected delegate int MyBinder<T>(object reader, ref T myObject); 
+1

Ich realisiere, dass Sie versuchen, die ursprünglichen Namen hier zu verstecken, aber Sie müssen das aufräumen. 'MyBinder' in' CallingMethod' ist nicht definiert, 'MyObjectBinder' wird nicht verwendet ... sind sie gleich? Ich kann nur versuchen, anzunehmen, und ich will das nicht tun ... – Randolpho

Antwort

103

Objekte werden nicht als Referenz übergeben. Objekte werden überhaupt nicht übergeben.

Standardmäßig wird der Wert des Arguments als Wert übergeben - unabhängig davon, ob dieser Wert ein Werttyp oder eine Referenz ist. Wenn ein Objekt über diese Referenz geändert wird, ist diese Änderung auch für den aufrufenden Code sichtbar.

In dem ursprünglich angezeigten Code gab es keinen Grund, ref zu verwenden. Das Schlüsselwort ref wird verwendet, wenn Sie eine Methode wünschen, die den Wert eines Parameters ändert (z. B. damit sie sich vollständig auf ein anderes Objekt bezieht) und diese Änderung für den Aufrufer sichtbar macht.

Jetzt, in der Code, den Sie (ursprünglich) gezeigt haben Sie habe nur:

private int BindMyObject(object reader, MyObject obj) 
{ 
    //make changes to obj in here 
} 

Haben Sie Code wie folgt bedeuten:

private int BindMyObject(object reader, MyObject obj) 
{ 
    obj = new MyObject(); 
} 

oder Code wie folgt:

private int BindMyObject(object reader, MyObject obj) 
{ 
    obj.SomeProperty = differentValue; 
} 

? Wenn es das letztere ist, dann brauchen Sie nicht ref. Wenn es der ehemalige ist, dann brauchen Sie tun müssen ref, weil Sie den Parameter selbst ändern, nicht Änderungen an dem Objekt, auf das der Wert bezieht. In der Tat, wenn Sie nur den Wert von obj setzen, ohne es jemals zu lesen, sollten Sie out anstelle von ref verwenden.

Wenn Sie ein kurzes aber vollständiges Programm zeigen können, das Ihr Problem demonstriert, wird es viel einfacher sein zu erklären, was vor sich geht.

Es ist schwer, dieses Thema in nur ein paar Absätzen gerecht zu werden - so habe ich eine entire article about it, die hoffentlich die Dinge offensichtlicher machen wird.

+1

Danke für die aktualisierte Antwort.Ja, das Problem lag daran, dass ich im BindMyObject ein neues Objekt initialisiert habe. Ich habe es gerade selbst entdeckt. – David

+1

@David Liddle - Sie könnten den geänderten Code in Ihr ursprüngliches Thema aufnehmen, so dass die Leute sehen, was Sie am Ende benutzt haben. Also ich nehme es Sie am Ende mit REF, dass Ihr Code ein neues myObject neu? – JonH

+1

@JonH: Ich habe meine Antwort ein wenig geändert, um es jetzt klarer zu machen, dass der Code geändert wurde :) –

Verwandte Themen