C#-在结构中强制子对象保持不变

时间:2018-10-24 14:18:53

标签: c# struct immutability

我正在尝试创建一个不变的结构。问题是,它内部包含可变对象。是否可以使这些不可变(不修改其类)?例如(https://dotnetfiddle.net/KTiTzB):

function takeTheDetails($categoryName){
    $option_arr = array_column($items,$categoryName);
    function generate_option($item, $key)
    {
        echo "<option>" . $item . "</option>";
    }

    $options = array_unique($option_arr[0], SORT_NUMERIC); // You can add array_unique and SORT_NUMERIC here
    asort($options);

    echo "<select>";
    array_walk_recursive($options, 'generate_option');
    echo "</select>";
};

takeTheDetails('diametru');

是否有一种方法可以使IntHolder成员不可变,同时不修改IntHolder类?

1 个答案:

答案 0 :(得分:1)

实际上是一个大问题:如何处理不可变数据中的嵌套对象?

  1. https://softwareengineering.stackexchange.com/questions/279580/how-to-make-complex-objects-immutable

  2. https://medium.freecodecamp.org/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5

  3. https://redux.js.org/recipes/structuringreducers/immutableupdatepatterns

我认为,创建不可变的子代模型以确保整个对象不可变是值得的。

请参见以下代码中的注释:

public class IntHolder
{
    public int X
    {
        get;
        set;
    }

    public ImmutableIntHolder ToImmutable()//convert itself to ImmutableIntHolder 
    {
        return new ImmutableIntHolder(X);
    }
}
public class ImmutableIntHolder
{
    public ImmutableIntHolder(int x)
    {
        X = x;
    }
    public int X
    {
        get;
        private set;
    }

    public IntHolder ToIntHolder() //convert it back to mutable IntHolder 
    {
        return new IntHolder()
        {
            X = this.X
        };
    }
}
public struct ImmutableStruct
{
    public int ImmutableInt
    {
        get;
        private set;
    }

    public ImmutableIntHolder IntHolder //use ImmutableIntHolder instead
    {
        get;
        private set;
    }

    public ImmutableStruct(int immutableInt, IntHolder myIntHolder) : this()
    {
        ImmutableInt = immutableInt;
        IntHolder = myIntHolder.ToImmutable(); // convert to immutable
    }
}

另一个选择是:

public class IntHolder
{
    public int X
    {
        get;
        set;
    }
}


public class ImmutableStruct //changed to class
{
    public int ImmutableInt
    {
        get;
        private set;
    }

    public ImmutableIntHolder IntHolder
    {
        get;
        private set;
    }

    public ImmutableStruct(int immutableInt, IntHolder myIntHolder) //: this()
    {
        ImmutableInt = immutableInt;
        IntHolder = new ImmutableIntHolder(myIntHolder); // convert here.
    }

    public class ImmutableIntHolder
    {
        public ImmutableIntHolder(IntHolder intHolder)
        {
            //map all properties
            X = intHolder.X;
        }
        public int X
        {
            get;
            private set;
        }
    }
}