我对延迟加载的方法有缺陷吗?

时间:2009-04-24 17:41:05

标签: c# resharper lazy-loading warnings

平台:带有Resharper 4.1,.NET 3.5的Visual Studio 2008 SP1

我有一个带静态方法的类,GetProperty<T>可以懒惰地返回属性值。

private static T GetProperty<T>(T backingField, Func<T> factory) 
    where T : class 
{
    if (backingField == null)
        backingField = factory();
    return backingField;
}

但是当我使用上面的方法返回一个属性时, 我收到两条警告,说没有分配私人支持字段。 但是只有在需要时才会分配它们。

alt text

此警告是否可忽略
- 或 -
我的加载财产是否存在缺陷?

4 个答案:

答案 0 :(得分:13)

你的方法存在缺陷。要采用此方法,您需要将backingField设为ref参数。

private static T GetProperty<T>(ref T backingField, Func<T> factory)

然后在GetProperty上传递ref _ImagXpressref _PdfXpress

你现在这样做只是为参数赋予一个新值,而不是为实际的后备字段赋值。

答案 1 :(得分:5)

你的方法存在缺陷。你的字段永远不会被设置为任何东西。 backingField方法中正在设置GetProperty<T>参数,但这不会更新您传入的字段。您需要使用附加的ref关键字传递该参数就像这样:

private static T GetProperty<T>(ref T backingField, Func<T> factory)

答案 2 :(得分:3)

正如我在另一个答案的评论中所述,对参数的需求是代码气味。首先,如果你在一个方法中执行此操作,那么你就违反了单一责任原则,但更重要的是,代码只能在你的继承层中重复使用。

这里有一个模式:

public class LazyInit<T>
    where T : class
{
    private readonly Func<T> _creationMethod;
    private readonly object syncRoot;
    private T _instance;

    [DebuggerHidden]
    private LazyInit()
    {
        syncRoot = new object();
    }

    [DebuggerHidden]
    public LazyInit(Func<T> creationMethod)
        : this()
    {
        _creationMethod = creationMethod;
    }

    public T Instance
    {
        [DebuggerHidden]
        get
        {
            lock (syncRoot)
            {
                if (_instance == null)
                    _instance = _creationMethod();
                return _instance;
            }
        }
    }

    public static LazyInit<T> Create<U>() where U : class, T, new()
    {
        return new LazyInit<T>(() => new U());
    }

    [DebuggerHidden]
    public static implicit operator LazyInit<T>(Func<T> function)
    {
        return new LazyInit<T>(function);
    }
}

这允许您这样做:

public class Foo
{
    private readonly LazyInit<Bar> _bar1 = LazyInit<Bar>.Create<Bar>();
    private readonly LazyInit<Bar> _bar2 = new LazyInit<Bar>(() => new Bar("foo"));

    public Bar Bar1
    {
        get { return _bar1.Instance; }
    }

    public Bar Bar2
    {
        get { return _bar2.Instance; }
    }
}

答案 3 :(得分:1)

提出不同的解决方案:

我会说,通过将该逻辑封装到一个单独的方法中,你并没有节省很多。你增加了你的复杂性而没有多少收获。我建议这样做:

protected PdfXpress PdfXpress
{
    get
    {
        if (_PdfXpress == null)
            _PdfXpress = PdfXpressSupport.Create();

        return _PdfXpress;
    }
}

protected ImagXpress ImagXpress
{
    get
    {
        if (_ImagXpress == null)
            _ImagXpress = IMagXpressSupport.Create();

        return _ImagXpress;
    }
}

您添加了几行,但大大降低了复杂性。