簡體   English   中英

C# - 在 Struct 中強制子對象不變性

[英]C# - Enforce Child Object Immutability in Struct

我正在嘗試創建一個不可變的結構。 問題是,它里面包含可變對象。 是否可以使那些不可變(不修改它們的類)? 例如( https://dotnetfiddle.net/KTiTzB ):

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

public struct ImmutableStruct
{
    public int ImmutableInt
    {
        get;
        private set;
    }

    public IntHolder MyIntHolder
    {
        get;
        private set;
    }

    public ImmutableStruct(int immutableInt, IntHolder myIntHolder): this ()
    {
        ImmutableInt = immutableInt;
        MyIntHolder = myIntHolder;
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Immutability");
        IntHolder intHolder = new IntHolder();
        intHolder.X = 40;
        Console.WriteLine(intHolder.X == 40); // TRUE
        ImmutableStruct immStruct = new ImmutableStruct(10, intHolder);
        Console.WriteLine(immStruct.ImmutableInt == 10); // TRUE
        // immStruct.ImmutableInt = 4; // THIS DOESN'T WORK, AS EXPECTED. Hurray!
        // immStruct.MyIntHolder = new IntHolder(3); // ALSO DOESN'T WORK, GOOD!
        immStruct.MyIntHolder.X = 4; // how can I prevent this from working?
    }
}

有沒有辦法在不修改 IntHolder 類的同時使 IntHolder 成員不可變?

這實際上是一個大問題:如何處理不可變數據中的嵌套對象?

  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-think-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;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM