2012-12-06 3 views
3
public class TreeNode 
{ 
    public TreeNode Left; 
    public TreeNode Right; 
    public int Data { get; set; } 

    public TreeNode(int data) 
    { 
     Left = null; 
     Right = null; 
     Data = data; 
    } 
} 



    public class BinarySearchTree 
{ 
    private TreeNode _root; 

    public BinarySearchTree() 
    { 
     _root = null; 
    } 

    public void Insert(int data) 
    { 
     TreeNode tempNode = null; 

     Insert(_root, tempNode); 
    } 

    private void Insert(TreeNode treeNode, TreeNode newNode) 
    { 
     newNode = new TreeNode(3); 
     treeNode = new TreeNode(4); 
    } 

В этом примере общественных недействительные Insert(int data) метод в основном только вызывает частный метод, и я ставлю точку останова в конце методы public void Insert(int data).C# Вопросы ссылочного типа

и уведомление _root по-прежнему отсутствует, а tempNode - 4. Я не понимаю, почему? Может ли кто-нибудь объяснить, пожалуйста?

+0

Содержит ли код? Где newNode определяется в Insert (int)? – manojlds

+0

Вы передаете ссылку по значению. Если вы выполнили treeNode.DoWork(), он будет действовать на объект, на который ссылается, но если вы переназначите treeNode, вы переназначаете саму ссылку (которая была передана по значению). – Michael

+1

Руководства по разработке рамок (книга Кшиштофа Квалины и Брэда Абрамса) рекомендуют избегать как параметров ref, так и out. Очень редко есть причина использовать 'out' и' ref'. –

ответ

3

Чтобы пройти классы ссылочного использованием ref ключевого слова:

private void Insert(ref TreeNode treeNode, ref TreeNode newNode) 
{ 
    newNode = new TreeNode(3); 
    treeNode = new TreeNode(4); 
} 

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

Измените метод Insert(data) (без ref ключевого слова компилятор выдаст ошибку):

public void Insert(int data) 
{ 
    TreeNode tempNode = null; 
    Insert(ref _root, ref tempNode); 
} 

Это фактически требование компилятора, просто чтобы убедиться, что абонент знает, что объект, передаваемый может быть заменен другой объект после вызова метода.

Вы также можете прочитать о ключевое слово out. В то время как параметры ref должны быть инициализированы перед вызовом, ожидается, что параметры метода инициализируются out внутри метода.

0

Вы передаете ссылочный тип, но на самом деле он передает копию справки. Обновление этой копии не обновляет оригинал.

Чтобы решить эту проблему, либо метод возвращает новое значение. Или вы можете переделать свою функцию, чтобы использовать параметры.

private void Insert(out TreeNode treeNode, out TreeNode newNode) 
{ 
    newNode = new TreeNode(3); 
    treeNode = new TreeNode(4); 
} 
+0

Здесь не должно быть ничего плохого в использовании 'ref', поскольку он создает новый объект, если он использует ключевое слово' ref' как в вызове функции, так и функции , –

+0

+1 всем предложениям по возврату/выходу. К сожалению, оригинальное название метода очень трудно понять, что ожидается поведение ... –

0

Посмотрите на out и ref модификаторы параметров. Например, вы могли бы

private void Insert(ref TreeNode treeNode, TreeNode newNode) 
Смежные вопросы