代码之家  ›  专栏  ›  技术社区  ›  Gradient

引用变量到实例成员

  •  0
  • Gradient  · 技术社区  · 6 年前

    我有这个数据类:

    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 在方法开始时,不要在mutliple中不必要地复制代码 如果 S.

    3 回复  |  直到 6 年前
        1
  •  0
  •   TheGeneral    6 年前

    你可以这样想

    当您将属性赋给局部变量时,

    var rightFooToModify = myclassInstance.Foo1;
    

    你所要做的就是写一张便条,上面写着一些记忆的位置。

    如果有人再给你一张便条,换上原来的

    rightFooToModify = new Foo();
    

    它不会改变原来的记忆,它还在那里,什么也没发生。

    指针/引用就是这样工作的。它们指向/引用内存中的某个位置,您可以复制一个引用,但覆盖该引用不会对原始内存位置产生任何影响,您只需将新的post-it注释指向其他位置即可。

    不过,现在我们来举一个非常巧妙的例子 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
    

    还有另一个奇怪的用法

    someClass.ModifyMyClass() = new Foo();
    someClass.ModifyMyClass().SomeValue = "I hope i never see this in my code base";
    Console.WriteLine(someClass.Foo1.SomeValue);
    
        2
  •  0
  •   Sam Arustamyan    6 年前

    我不知道这是否有帮助,但是可以有一个方法返回正确的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;
        }
    }
    

    然后这样称呼:

    GetFooSetter()(myClassInstance, new Foo());
    
        3
  •  0
  •   Ofir Winegarten    6 年前

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

    1. 如果 Foo 不是不可变的,那么只需修改它的值,而不是将其分配给新实例。您甚至可以添加一个复制函数来从另一个 :

      Foo fooToChange = myClassInstance.Foo1;
      fooToChange.CopyFrom(new Foo());
      
    2. 重构以将foo保存在一个数组中,然后您可以请求它并使用索引进行分配:

      class MyClass
      {
          public Foo[] Foos = new Foo[4];
      }
      
      int fooToChange = 3;
      myClassInstance.Foos[3] = new Foo();