Передача объектов и список объектов по ссылке в C # - PullRequest
40 голосов
/ 14 июня 2010

У меня есть делегат, который модифицирует объект.Я передаю объект делегату из вызывающего метода, однако вызывающий метод не принимает эти изменения.Тот же код работает, если я передаю 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 Ответ

105 голосов
/ 14 июня 2010

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

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

В коде, который вы показали изначально, не было причин использовать 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. Если это первое, то вам do нужно ref, потому что вы изменяете сам параметр, а не вносите изменения в объект, к которому относится значение. Фактически, если вы просто устанавливаете значение obj, даже не читая его, вы должны использовать out вместо ref.

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

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

...