实例成员的引用变量

时间:2018-09-30 03:24:08

标签: c# reference

我有这个数据类:

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 :(得分:0)

您可以这样想

将属性分配给局部变量时,

var rightFooToModify = myclassInstance.Foo1;

您要做的就是写一个便签纸,上面留有一些内存。

如果有人给您另一个便条纸,则替换原始便条纸

rightFooToModify = new Foo();

它不会改变原始内存,它仍然存在,什么也没发生。

这是指针/引用的工作方式。它们指向/引用内存中的位置,您可以复制引用但覆盖该引用对原始内存位置没有任何作用,只是有一个指向其他地方的新便笺。

但是,现在举一个用ref returnref 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

还有另一个奇怪而怪异的引用用法

someClass.ModifyMyClass() = new Foo();
someClass.ModifyMyClass().SomeValue = "I hope i never see this in my code base";
Console.WriteLine(someClass.Foo1.SomeValue);

答案 1 :(得分:0)

我不知道这是否有帮助,但是您可以使用一种方法来返回类型为boolean win() { return (fc == 3 && fm == 3) ? false : true; /// or better: return !(fc == 3 && fm == 3); } 的正确的setter,即

Action<MyClass, Foo>

然后这样称呼它:

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

答案 2 :(得分:0)

用例不太清楚,所以我建议两个选择:

  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();