gtk #: объект дерева просмотра всегда передается как вызов по ссылке - PullRequest
0 голосов
/ 03 ноября 2018

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

У меня есть видимый элемент управления GTK «Tree View» в окне верхнего уровня. Данные были записаны соответствующей моделью.

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

Чтобы удалить столбцы только из выходных данных, а не из самого графического интерфейса, я подумал о том, чтобы скопировать видимый элемент управления Tree View во временный, манипулировать временным и вызывать функцию экспорта для временного.

Моя проблема: несмотря на то, что я передаю свое происхождение, видимое древовидное представление как референс по значению (насколько я понимаю), происхождение будет изменено, и удаление визуальных столбцов будет выполнено в визуальном древовидном представлении.

Кажется, что мои аргументы в вызове метода всегда выполняются как вызов по ссылке.

Код:

"treeview1" - это визуальный вид Gtk.Tree ...

Я вызываю свою функцию экспорта:

...
TreeView treeviewExport = SetExportViewAccordingToCheckboxes(treeview1);                
ExportFile(treeviewExport);
...

В методе SetExportViewAccordingToCheckboxes () я просто передаю глобальное treeview1 как вызов по значению, манипулирую им внутри и возвращаю манипулируемое древовидное представление:

protected static TreeView SetExportViewAccordingToCheckboxes(TreeView tvSource)
{
        TreeView tvRet = tvSource;

        if (cbName == false)
            tvRet.RemoveColumn( ... );
            ...
return tvRet;
}

Но даже несмотря на то, что я удалил столбцы из внутреннего дерева "tvRet", в моем визуальном элементе управления "treeview1" отсутствуют все столбцы, которые были удалены из "tvRet"; похоже, что "treeview1" был передан как вызов по ссылке.

Вопрос: почему это так?

Примечание: я также пробовал с ключевым словом "in", которое не имело никакого значения:

protected static TreeView SetExportViewAccordingToCheckboxes(in TreeView p_tvSource)

1 Ответ

0 голосов
/ 06 ноября 2018

Проблема возникает здесь:

В методе SetExportViewAccordingToCheckboxes () я просто передаю глобальный treeview1 как вызов по значению, манипулировать им внутри и возвращать манипулируемый вид дерева:

protected static TreeView SetExportViewAccordingToCheckboxes(TreeView tvSource)
{
    TreeView tvRet = tvSource;

    if (cbName == false)
        tvRet.RemoveColumn( ... );
        ...
    return tvRet;
}

Сначала немного предыстории. В терминологии C # типы значений - это те, которые непосредственно содержат значение, в то время как ссылочные типы - это те, которые ссылаются на данные, а не хранят их непосредственно.

Итак, int x = 5 означает, что вы создаете объект значения 5 типа integer и сохраняете его в x, тогда как TreeView tree = new TreeView() означает, что вы создаете ссылку tree типа TreeView , который указывает на объект того же типа.

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

Итак, следующий шаг - скопировать данные и изменить скопированный объект вместо исходного. Это теоретически обоснованно, но строка: TreeView tvRet = tvSource;, к сожалению, этого не достигает. Да, вы создаете новую ссылку, но эта ссылка указывает на тот же объект, на который указывает исходная ссылка.

Теперь предположим, что мы управляем объектами класса Точка вместо TreeView со свойствами x и y .

class Point {
    public int X { get; set; }
    public int Y { get; set; }
}

Вы можете легко создать точку:

Point p1 = new Point { X = 5, Y = 7 };

Но это не копирует это:

Point p2 = p1;

Это будет делать:

Point p2 = new Point { X = p1.X, Y = p1.Y };

Теперь исходная проблема заключалась в том, что вы хотели передать несколько столбцов в функцию Export () . В этом случае вам нужно только передать вектор отфильтрованных столбцов в функцию экспорта вместо копии TreeView .

void PrepareExporting()
{
    var columns = new List<TreeViewColumn>();

    foreach(TreeViewColumn col in this.treeView.Columns) {
        if ( this.Filter( col ) ) {
            columns.add( col );
        }
    }

    this.Export( columns.ToArray() ); 
}

void Export(TreeViewColumn[] columns)
{
    // ...
}

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

Надеюсь, это поможет.

...