簡體   English   中英

在 C# 中使用默認構造函數初始化只讀成員變量

[英]Initializing a readonly member variable with a default constructor in C#

我的代碼中有一個簡單的工廠實現。 我的目標是讓構造的對象保留對創建它們的工廠的引用,因此我將它們連接起來類似於:

public class Factory {

    public T CreateObject<T>() where T : Foo, new() 
    {
        return new T() {
            parent = this
        };
    }
}

public class Foo {

    internal Factory parent;
    internal Foo() { }
}

這就像它所讀的那樣有效,但我一直在想我可能想要那個parent變量,這樣一旦工廠設置它就不能改變它。 但是,如果我將其聲明為internal readonly Factory parent; ,那么工廠就不能再在施工時設定它的價值了。

我通常會通過提供一個帶參數的構造函數來解決這個問題,但這會殺死通用實現,因為 AFAIK where T: new()意味着一個無參數的構造函數。

我的 C# 排骨可能只是缺少一些齒輪,但是對於 go 實施這樣的事情,最好的方法是什么? (或者最好放棄readonly並相信代碼不會以不安全的方式修改parent --- NullReferenceException s會浮現在腦海中---?)

您可以使用反射來設置字段,無論readonly修飾符如何,這都將起作用:

public class Factory
{
    public T CreateObject<T>() where T : Foo, new()
    {
        T t = new T();
        t.GetType()
         .GetField("parent", BindingFlags.NonPublic | BindingFlags.Instance)
         .SetValue(t, this);
        return t;
    }
}

我不認為你能得到你想要的東西,但你可以創建一個只能分配一次的屬性,然后讓工廠覆蓋它。 但我想用戶總是可以用new CreatingFactory強制覆蓋,但我認為這使它變得困難並且至少清楚地表明了你的意圖。

您可以執行以下操作。

    class Foo
    {
        private Factory factory;

        public Factory CreatingFactory
        {
            get { return factory; }
            set
            {
                if (factory != null)
                {
                    throw new InvalidOperationException("the factory can only be set once");
                }
                factory = value;
            }
        }
    }

    class Factory
    {
        public T Create<T>()
            where T : Foo, new()
        {
            T t = new T()
            {
                CreatingFactory = this
            };
            return t;
        }
    }

創建它后,我搜索並找到了一個可能比我更好的答案: Is there a way to set a property only in C#

我不確定這是否正是您想要的,但我想出了一種方法,用Func替換您的泛型類型參數,該方法顯示如何構造Foo object 並允許您在構造函數中設置父級。

public class Factory {
    private Func<Factory, Foo> creator;

    public Factory(Func<Factory, Foo> creator) {
        this.creator = creator;
    }

    public Foo CreateObject()
    {
        return this.creator(this);
    }
}

public class Foo {
    internal readonly Factory parent;
    internal Foo(Factory parent) {
        this.parent = parent;
    }
}

接着

public void Main() {
    Factory myfactory = new Factory(fact => new Foo(fact));
    Foo myfoo = myfactory.CreateObject();
}

暫無
暫無

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

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