Передача объектов и список объектов по ссылке в C#

У меня есть делегат, который изменяет объект. Я передаю объект делегату из вызывающего метода, однако вызывающий метод не принимает эти изменения. Тот же код работает, если я передаю List как объект.

Я думал, что все объекты были переданы по ссылке, поэтому любые изменения будут отражены в вызывающем методе. Это верно?

Я могу изменить свой код, чтобы передать ref возражать против делегата. Но мне интересно, почему это необходимо. Либо это?

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
}

Обновить:

Я сейчас прохожу мимо объектов ref делегату, как я создаю новый объект внутри BindMyObject,

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

1 ответ

Решение

Объекты не передаются по ссылке. Объекты не передаются вообще.

По умолчанию значение аргумента передается по значению - является ли это значение значением типа значения или ссылкой. Если объект изменяется с помощью этой ссылки, то это изменение будет видно и для вызывающего кода.

В коде, который вы показали изначально, не было никакой причины использовать ref, ref Ключевое слово используется, когда вам нужен метод, который изменяет значение параметра (например, чтобы он полностью ссылался на другой объект) и имел это изменение видимым для вызывающей стороны.

Теперь, в коде, который вы показали (изначально), вы получили только:

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

Вы имеете в виду код такой:

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

или код как это:

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

? Если это последнее, то вам не нужно ref, Если это первое, то вам нужно ref потому что вы изменяете сам параметр, а не вносите изменения в объект, к которому относится значение. На самом деле, если вы просто устанавливаете значение obj не читая его, вы должны использовать out вместо ref,

Если вы сможете показать короткую, но полную программу, которая демонстрирует вашу проблему, вам будет гораздо проще объяснить, что происходит.

Трудно сделать эту тему справедливой всего в нескольких параграфах - поэтому у меня есть целая статья об этом, которая, мы надеемся, сделает вещи более очевидными.

Другие вопросы по тегам