Тип ссылки по-прежнему нуждается в передаче по ссылке?

Рассмотрим следующий код (для простоты я не следовал правилам кодирования C #).

public class Professor { public string _Name; public Professor(){} public Professor(string name) { _Name=name; } public void Display() { Console.WriteLine("Name={0}",_Name); } } public class Example { static int Main(string[] args) { Professor david = new Professor("David"); Console.WriteLine("\nBefore calling the method ProfessorDetails().. "); david.Display(); ProfessorDetails(david); Console.WriteLine("\nAfter calling the method ProfessorDetails().."); david. Display(); } static void ProfessorDetails(Professor p) { //change in the name here is reflected p._Name="Flower"; //Why Caller unable to see this assignment p=new Professor("Jon"); } } 

Как и ожидалось, выход:

Перед вызовом метода ProfessorDetails () …

Имя = Давид

После вызова метода ProfessorDetails () …

Имя = Цветок

Вызов p=new Professor("Jon"); в ProfessorDetails(Professor p) не эффективен, хотя он является ссылочным типом. Почему мне нужно использовать ключевое слово ref для получения желаемого результата?

Все передается по значению в C #. Однако, когда вы передаете ссылочный тип, сама ссылка передается по значению , т. Е. Передается копия исходной ссылки. Таким образом, вы можете изменить состояние объекта, на которое указывает ссылочная копия, но если вы присвоите новое значение ссылке, вы изменяете только то, на что указывает копия, а не исходная ссылка.

Когда вы используете ключевое слово ‘ref’, он сообщает компилятору передать исходную ссылку, а не копию, поэтому вы можете изменить то, что указывает на внутреннюю часть функции. Тем не менее, необходимость в этом обычно бывает редкой и чаще всего используется, когда вам нужно вернуть несколько значений из метода.

Пример:

 class Foo { int ID { get; set; } public Foo( int id ) { ID = id; } } void Main( ) { Foo f = new Foo( 1 ); Console.WriteLine( f.ID ); // prints "1" ChangeId( f ); Console.WriteLine( f.ID ); // prints "5" ChangeRef( f ); Console.WriteLine( f.ID ); // still prints "5", only changed what the copy was pointing to } static void ChangeId( Foo f ) { f.ID = 5; } static void ChangeRef( Foo f ) { f = new Foo( 10 ); } 

У вас есть проход по ссылке и ссылочный тип, смешанный.

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

Существует разница между передачей ссылки и ссылкой на ссылку.

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

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

Фактическое значение p является ссылкой на тот же экземпляр профессора, что и Дэвид. Любые вызовы, которые вы делаете по этой ссылке, разыменовываются как вызовы того же экземпляра, что и вызовы, сделанные на david be. Однако p является копией этой ссылки, это не то же самое, что значение david.

Таким образом, когда вы p = new Professor (), вы изменяете значение ссылочной переменной, чтобы указать на новый экземпляр. Однако это не изменяет ссылку david, которая все еще указывает на старый экземпляр.

Если вы должны были передать p как ref, значение p будет ссылкой на ссылочную переменную david. Модификация этого файла фактически изменит значение david, чтобы указать на новый экземпляр.

Что касается «передачи ссылочного типа» vs ‘, проходящего по ref (с помощью ключевого слова ref), то после моего исследования я забираю это:

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

Но на вашем пути перехода от одного метода к другому, если вы создадите новую ссылку для объекта (как вы это делаете, написав «p = new Professor (« Jon »)), вы в основном нарушаете связь между объект в новом методе и исходном объекте. Ваш «p» теперь ссылается на другое место в памяти. Поэтому, независимо от того, какое изменение вы сделаете в этом новом месте памяти, оно не будет иметь никакого эффекта для исходного объекта. Однако, если вы хотите изменить исходный адрес объекта и иметь ссылку, вам нужно использовать ключевое слово ref. ОСОБЕННОСТИ ИСПОЛЬЗОВАНИЯ REF KEYWORD, потому что один раз в любом способе вы делаете исходный адрес в смене памяти на новый адрес (используя ключевое слово ref), все изменения исходного объекта, выполненные другими методами, теперь исчезли.

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

 public class Professor { public string _Name; public Professor(){} public Professor(string name) { _Name=name; } public void Display() { Console.WriteLine("Name={0}",_Name); } } public class Example { static int Main(string[] args) { Professor david = new Professor("David"); Console.WriteLine("\nBefore calling the method ProfessorDetails().. "); david.Display(); ProfessorDetails(ref david); Console.WriteLine("\nAfter calling the method ProfessorDetails().."); david. Display(); } static void ProfessorDetails(ref Professor p) { //change in the name here is reflected p._Name="Flower"; //Why Caller unable to see this assignment p=new Professor("Jon"); } } 
  • Что более эффективно: вернуть значение против Pass by reference?
  • Только для поклонников в facebook с asp.net C # sdk
  • Моческое статическое свойство с moq
  • Как передать 2D-массив (матрицу) в функции в C?
  • Как программно изменить пароль Active Directory
  • Как скомпилировать Qt 5 под Windows или Linux, 32 или 64 бит, статические или динамические на VS2010, VS2012, VS2013 или VS2015 Express или g ++
  • Каков наилучший способ сделать математику с фиксированной запятой?
  • Переопределение общедоступных виртуальных функций с частными функциями в C ++
  • Поиск различий свойств между двумя объектами C #
  • CallbackOnCollectedDelegate в globalKeyboardHook был обнаружен
  • Разница между malloc и calloc?
  • Interesting Posts

    Удаление сопоставлений маршрутов в NodeJS Express

    Как вы указываете тип проекта Visual Studio из существующего проекта Visual Studio

    Выключение вывода консоли управления спящего режима

    71mb добавлено в размер приложения для пешеходного перехода

    Автоматически искать обновления драйверов?

    Как Xml Documentation для Web Api включает документацию из-за основного проекта?

    Корпоративная библиотека Unity vs Other IoC Containers

    как добавить параметры командной строки при запуске java-кода в Eclipse?

    ArrayAdapter в android для создания простого списка

    WCF. Сервисные общие методы

    Как избежать тупика mysql, обнаруженного при попытке получить блокировку; попробуйте перезапустить транзакцию “

    Изменение горячих клавиш CTRL-X, -C и -V в Windows на разные клавиши

    Скопировать все файлы, созданные через определенный час в командной строке (Windows)?

    Как установить курсор на HTML-контент при открытии новой вкладки Firefox?

    Циклическая зависимость между файлами заголовка

    Давайте будем гением компьютера.