Ссылочная переменная для члена экземпляра - PullRequest
0 голосов
/ 30 сентября 2018

У меня есть этот класс данных:

class MyClass
{
    Foo Foo1 { get; set; }
    Foo Foo2 { get; set; }
    Foo Foo3 { get; set; }
    Foo Foo4 { get; set; }
}

Теперь, где-то еще в моей программе, у меня есть эта функция:

void ModifyMyClass(MyClass myClassInstance)
{
    var rightFooToModify = myclassInstance.Foo1;

    rightFooToModify = new Foo();  // Here, my intention is to
                                   // modify MyClass, not just the
                                   // local variable 'rightFooToModify'
}

Мне нужно иметь возможность выбрать один из Foo1, Foo2, Foo3, Foo4 (в зависимости от некоторых условий) и затем установите его для нового объекта Foo.

Каков наилучший способ достижения этого?Есть ли какая-нибудь ссылочная переменная, которую я могу использовать для этого в C #?

РЕДАКТИРОВАТЬ:

Я мог бы использовать (и это на самом деле то, что я использую сейчас):

myClassInstance.Foo1 = new Foo();

Но ModifyMyClass () на самом деле немного сложнее, например:

void ModifyMyClass(MyClass myClassInstance)
{
    if (someCondition)
    {
        var rightFooToModify = myClassInstance.Foo1
        // ... Do some computation with rightFooToModify
        myClassInstance.Foo1 = new Foo(/* some parameters */);
    }
    else if (someOtherCondition)
    {
        // The exact same code as the if above , but with
        // myClassInstance.Foo2 instance.
    }
}

Я бы хотел избежать дублирования кода в блоке if во всехследующее else if.Вот почему я хотел бы просто использовать var rightFooToModify = myClassInstance.Foo1 в начале метода и не дублировать код без необходимости в нескольких if s.

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Я не знаю, поможет ли это, но у вас может быть метод, возвращающий правильный установщик типа Action<MyClass, Foo>, то есть

Action<MyClass, Foo> GetFooSetter()
{
    if (someCondition)
    {
        return (myClass, foo) => myClass.Foo1 = foo;
    }
    else if (someOtherCondition)
    {
        return (myClass, foo) => myClass.Foo2 = foo;
    }
}

, и затем вызывайте его так:

GetFooSetter()(myClassInstance, new Foo());
0 голосов
/ 30 сентября 2018

Вариант использования не очень понятен, поэтому я предложу два варианта:

  1. Если Foo не является неизменяемым, просто измените его значения вместо назначения его новомупример.Вы даже можете добавить функцию копирования для копирования значений из другого Foo:

    Foo fooToChange = myClassInstance.Foo1;
    fooToChange.CopyFrom(new Foo());
    
  2. Рефакторинг для хранения Foos в массиве, затем вы можете запросить его и назначить с помощьюиндекс:

    class MyClass
    {
        public Foo[] Foos = new Foo[4];
    }
    
    int fooToChange = 3;
    myClassInstance.Foos[3] = new Foo();
    
0 голосов
/ 30 сентября 2018

Вы можете думать об этом так:

Когда вы присваиваете свое свойство локальной переменной,

var rightFooToModify = myclassInstance.Foo1;

все, что вы делаете - это пишите заметку с указанием местоположениянемного памяти на.

Если кто-то дает вам еще одну заметку с некоторыми дополнительными примечаниями, заменяя исходную

rightFooToModify = new Foo();

Она не меняет исходную память, она все еще там, ничего не произошло.

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

Однако, теперь для действительно надуманного примера способа преодолеть это с ref return и ref Local

Отказ от ответственности, я действительно не рекомендую делать это в вашей ситуации, однако для чисто академических целей давайте рассмотрим эту языковую особенность

Учитывая

public class MyClass
{
   private Foo _foo1;

   public Foo Foo1
   {
      get => _foo1;
      set => _foo1 = value;
   }

   public ref Foo ModifyMyClass()
   {
      return ref _foo1;
   }
}

Пример

// create class
var someClass = new MyClass();

// create some memory for it
someClass.Foo1 = new Foo();
someClass.Foo1.SomeValue = "test";

// copy the reference to it
var copy = someClass.Foo1; 

// overwrite it
copy = new Foo();
copy.SomeValue = "test2";

// oh nossssssssss!!!! is didn't change!!
Console.WriteLine(someClass.Foo1.SomeValue);


//enter ref local
ref var  actualLocation = ref someClass.ModifyMyClass();

// create some memory
actualLocation = new Foo();
actualLocation.SomeValue = "test3";

// omg it worked!!!!
Console.WriteLine(someClass.Foo1.SomeValue);

Вывод

test
test3

И еще одно странное и странное использование ref

someClass.ModifyMyClass() = new Foo();
someClass.ModifyMyClass().SomeValue = "I hope i never see this in my code base";
Console.WriteLine(someClass.Foo1.SomeValue);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...