繁体   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