8

我目前正在更改一个广泛使用的类,以将尽可能多的昂贵初始化从类构造函数转移到惰性初始化属性中。下面是一个示例(在 c# 中):

前:

public class ClassA
{
    public readonly ClassB B;

    public void ClassA()
    {
        B = new ClassB();
    }
}

后:

public class ClassA
{
    private ClassB _b;

    public ClassB B
    {
        get
        {
            if (_b == null)
            {
                _b = new ClassB();
            }

            return _b;
        }
    }
}

在我正在更改的类中还有相当多的这些属性,有些在某些情况下没有使用(因此是懒惰),但如果它们被使用,它们很可能会被重复调用。

不幸的是,这些属性也经常在类内部使用。这意味着私有变量 (_b) 有可能直接由方法使用,而无需对其进行初始化。

有没有办法在类中只提供公共属性(B),或者甚至是在需要时具有相同初始化的替代方法?

这是从程序员转发的(显然不够主观): https ://softwareengineering.stackexchange.com/questions/34270/best-methods-for-lazy-initialization-with-properties

4

3 回答 3

16

好吧,我推荐的解决方案是告诉您的同事使用该属性,而不是该字段。但是你可以像这样在某种程度上证明它是白痴:

public class ClassA
{
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());

    public ClassB B
    {
        get
        {
            return _b.Value;
        }
    }
}

现在很难搞砸了。

于 2011-01-06T15:59:42.603 回答
6

您可以考虑将惰性属性推送到基类中,以避免直接访问支持变量。我知道不理想。我一直认为这是 C# 中缺乏的东西,即对惰性属性的直接支持。

于 2011-01-06T16:00:58.757 回答
3

@chibacity 发布(并随后)删除 [然后取消删除:P] 使用抽象基类的替代选项。虽然它在代码分发方面可能并不理想,但它确实提供了一个很好的封装,消除了许多代码混乱,从而使 ClassA 更简洁。例如,您可以考虑结合这些技术来实现这两个目标:

public class ClassB { /* Class to be lazily instantiated */ }

public abstract class BaseA
{
    private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());
    public virtual ClassB B { get { return _b.Value; } }
}

public class ClassA : BaseA
{
    public override ClassB B { get { return base.B; } }
}

乍一看,这似乎更冗长,但是当您考虑 ClassA 是您将要使用的类时,这意味着您的所有引用都经过相同的属性 - 没有多余的不必要的导致潜在混乱的字段,没有绕过属性直接引用_b,也没有必要告诉你的同事使用哪个......只有一个。

不是说这是正确的方法,或者这是一种应该或不应该遵循的模式,我只是指出@chibacity 建议的优点,否则可能会被忽视。

如果您可以在不必引用 B.Value 的情况下拥有隐式延迟加载属性,那就太好了...例如:

[Lazy]
public ClassB B { get; }

或者对于没有无参数构造函数的对象

[Lazy(() => new ClassB("Hello", "World"))]
public ClassB B { get; }

或者正如@chibacity 在评论中建议的那样

public ClassB B { lazyget; }

或者

public ClassB B { lazyget : new ClassB(); }

唉,我不认为这些都是目前任何形式的可用解决方案......

于 2011-01-06T16:55:15.867 回答