静态字段或属性只被初始化一次吗?

3
以下代码中,每次调用 Test.someBaseField 或 Test.someBaseProperty,都会导致该函数被调用并创建一个新的 SomeBase 实例吗?或者这只会在最开始发生一次? 如何设置为后者(在最开始时仅调用一次)?
public class SomeBase {}
public class SomeObjectA : SomeBase {}
public class SomeObjectB : SomeBase {}

public class Test
{
    public static bool someBool = true;

    public static SomeBase someBaseField = GetBase(someBool);
    public static SomeBase someBaseProperty { get { return GetBase(someBool); } }

    public static SomeBase GetBase(bool getA)
    {
        if(getA)
            return new SomeObjectA() as SomeBase;       
        else
            return new SomeObjectB() as SomeBase;
    }
}

4
该字段只初始化一次。每次访问属性时,都会执行属性的getter方法,因此每次访问时都会调用GetBase方法。这里提供了一个参考链接:http://msdn.microsoft.com/en-us/library/aa645758.aspx。 - Blorgbeard
如果我在另一个类中有一个属性引用Test.someBaseProperty,那么它会在每次调用时动态设置,对吗?而如果我有一个字段引用Test.someBaseProperty,它将仅被设置一次,即其初始值,对吗?再次感谢! - user2994682
我已经编辑了你的标题。请参阅“问题标题应该包含‘标签’吗?”,在那里达成共识是“不应该”。 - John Saunders
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3

每次调用基类都会被称为"base",并且每次都会返回一个新的"somebase"实例。这种情况被称为工厂模式。

您想要做的是创建一个单例模式。有很多方法可以创建单例模式,但最流行的方法是跟踪某个字段或属性,并在初始化后每次都返回它,如果尚未初始化,则进行初始化。

因此,您需要做的是:

static someBase _trackingVar;
public static someBase someProperty{ 
    get
    {
        if(_trackingVar == null){
            _trackingVar = GetBase(...);
        }
        return _trackingVar;
    }
}

这种方法的一个问题是它不是线程安全的。有一种线程安全版本的单例创建方法。详见http://msdn.microsoft.com/en-us/library/ff650316.aspx


1
每次调用 "new" 都会创建一个类 "SomeBase" 的新实例。因此,在您的情况下,这两行代码将创建两个新实例。
public static SomeBase someBaseField = GetBase(someBool);
public static SomeBase someBaseProperty { get { return GetBase(someBool); } }
请注意,在这两种情况下,您只是将引用设置为静态的。静态引用对对象创建没有影响。 如果您只想创建一个对象,请使用私有字段:
private static SomeBase _someBaseField = null; 
在GetBase()中添加一个空值检查,如下所示:

在以下位置添加一个空值检查:

if (_someBaseField == null)
{
    _someBaseField = new SomeObjectA() as SomeBase; 
    return _someBaseField;
}
else 
{
    return _someBaseField;
}

可选地,您可以更改someBaseProperty,以便您也可以在内部使用属性设置器。

public static SomeBase someBaseProperty 
{
    get { return GetBase(someBool); }
    private set(value) { _someBaseField = value; }
}

没有必要将该字段公开。


someBaseProperty 调用 GetBase,因此您已经创建了相互无限递归... 但是 someBaseProperty 没有 setter,所以它不会编译 :P - Blorgbeard
什么是“相互无限递归”?我认为它不会创建递归。是的,对于someBaseProperty,必须有setter。 - Rabi
你在GetBase()中添加的代码调用了someBaseProperty的getter方法。someBaseProperty的getter方法又调用了GetBase()方法。 - Blorgbeard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,