web-dev-qa-db-fra.com

Passer des objets et une liste d'objets par référence en C #

J'ai un délégué qui modifie un objet. Je passe un objet au délégué à partir d'une méthode d'appel, mais la méthode d'appel ne reprend pas ces modifications. Le même code fonctionne si je passe un List comme objet.

Je pensais que tous les objets étaient passés par référence afin que toute modification soit reflétée dans la méthode d'appel. Est-ce exact?

Je peux modifier mon code pour passer un objet ref au délégué. Mais je me demande pourquoi cela est nécessaire. Ou est-ce?

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
}

Mise à jour:

Je passe maintenant des objets par ref au délégué car j'instancie un nouvel objet à l'intérieur de BindMyObject.

protected delegate int MyBinder<T>(object reader, ref T myObject);
40
David

Les objets ne sont pas transmis par référence. Les objets ne sont pas du tout passés.

Par défaut, la valeur de l'argument est transmise par valeur - que cette valeur soit une valeur de type valeur ou une référence. Si un objet est modifié via cette référence, ce changement sera également visible pour le code appelant.

Dans le code que vous avez montré à l'origine, il n'y avait aucune raison d'utiliser ref. Le mot clé ref est utilisé lorsque vous voulez une méthode qui modifie la valeur d'un paramètre (par exemple pour le faire référence à un objet différent entièrement) et que ce changement soit visible pour l'appelant.

Maintenant, dans le code que vous avez montré (à l'origine), vous n'avez que:

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

Voulez-vous dire un code comme celui-ci:

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

ou un code comme celui-ci:

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

? Si c'est le dernier, alors vous n'avez pas besoin de ref. Si c'est le premier, alors vous avez besoin de ref parce que vous modifiez le paramètre lui-même, sans apporter de modifications à l'objet que le valeur fait référence à. En fait, si vous définissez simplement la valeur de obj sans jamais la lire, vous devez utiliser out au lieu de ref.

Si vous pouvez montrer un programme court mais complet qui illustre votre problème, il sera beaucoup plus facile d'expliquer ce qui se passe.

Il est difficile de rendre justice à ce sujet en quelques paragraphes - j'ai donc un article entier à ce sujet , ce qui, espérons-le, rendra les choses plus évidentes.

105
Jon Skeet