Почему мы не можем назначить объект напрямую методу, который возвращает тот же тип? - PullRequest
0 голосов
/ 06 июня 2018

Я спрашиваю об этом из любопытства, и я знаю о других способах сделать это.

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

Зачем нам нужно указывать ссылку на локальную переменную для изменения самого объекта?

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

См. Пример кода ниже:

static Demo StaticDemoInstance;
static void Main(string[] args)
{
    //allowed: means I can directly modify property of static instance
    //  received from method
    GetDemo().Name = "UpdateDemo";

    //allowed: means I can get instance and overwrite it with other instance
    //      but not directly from method
    Demo d = GetDemo();
    d = new Demo("NewCreatedDemo", false);

    //not allowed: means I can't do second step directly on method
    //  question: 
    //      when I can update instance property without receiving instance on local variable
    //      what possible violation/difficulty (in compiler) will be there so it doesn't allow this
    GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);
}

static Demo GetDemo() => StaticDemoInstance ?? 
                         StaticDemoInstance = new Demo("StaticDemo", false);

1 Ответ

0 голосов
/ 06 июня 2018

Вы всегда можете использовать Ref return

Начиная с C # 7.0, C # поддерживает эталонные возвращаемые значения (ref return).Ссылочное возвращаемое значение позволяет методу возвращать ссылку на переменную, а не на значение, обратно к вызывающей стороне.Вызывающий объект может затем выбрать обработку возвращенной переменной, как если бы она была возвращена по значению или по ссылке.Вызывающая сторона может создать новую переменную, которая сама является ссылкой на возвращаемое значение, которая называется ref local.

Ограничения

Есть некоторыеограничения на выражение, которое метод может возвращать в качестве ссылочного возвращаемого значения.Ограничения включают:

  • Возвращаемое значение должно иметь время жизни, которое выходит за рамки выполнения метода.Другими словами, это не может быть локальной переменной в методе, который ее возвращает.Это может быть экземпляр или статическое поле класса или аргумент, передаваемый методу.Попытка вернуть локальную переменную приводит к ошибке компилятора CS8168: «Невозможно вернуть локальный объект obj по ссылке, поскольку он не является ссылочным локальным.»

  • Возвращаемое значение не может быть буквальным нулем.Возврат значения null приводит к ошибке компилятора CS8156: «Вы не можете использовать выражение в этом контексте, поскольку оно не может быть возвращено по ссылке.»

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

  • Возвращаемое значение не может быть константой, элементом перечисления, возвращаемым значением по значениюиз свойства, или метода класса или структуры.Нарушение этого правила приводит к ошибке компилятора CS8156: «Вы не можете использовать выражение в этом контексте, потому что оно не может быть возвращено по ссылке.»

Действительно надуманный пример ине то, что я рекомендую , однако оно достигает ваших целей (академически)

Пример

static Demo StaticDemoInstance;

...

static ref Demo GetDemo()
{
   if (StaticDemoInstance == null)
      StaticDemoInstance = new Demo("StaticDemo", false);

   return ref StaticDemoInstance;
}

..

GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);

Обновление

Использование этого может быть замечено с дальнейшим запутанным примером и модификациями

Exmaple

static Demo Test()
{
   return StaticDemoInstance;
}

...

GetDemo() = new Demo("UpdatedDemoFromGetMeth", false);
var someObject = Test();
someObject= new Demo("Test", false);

Console.WriteLine(StaticDemoInstance.Name);
Console.WriteLine(someObject.Name);

Выход

UpdatedDemoFromGetMeth
Test

Метод Test (не ref ref) и дает вам только копию ссылки (из-за отсутствия лучшей терминологии), если вы перезаписаете ее, ваша статическая переменная на StaticDemoInstance не изменится

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...