0

平台:带有 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;
}

但是,当我使用上述方法返回属性时,我收到两个警告,指出未分配私有支持字段。但只有在需要时才会分配它们。

替代文字

这个警告可以忽略吗?
-- 或者 --
我加载属性的方法有缺陷吗?

4

4 回答 4

13

你的方法有缺陷。要采用这种方法,您需要创建backingField一个ref参数。

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

然后GetProperty,通过ref _ImagXpressref _PdfXpress

您现在执行的方式只是为参数分配一个新值,而不是实际的支持字段。

于 2009-04-24T17:44:26.523 回答
5

你的方法有缺陷。你的领域永远不会被设置为任何东西。该backingField参数正在GetProperty<T>方法中设置,但这不会更新您传入的字段。您需要传入带有ref附加关键字的参数,如下所示:

private static T GetProperty<T>(ref T backingField, Func<T> factory)
于 2009-04-24T17:46:27.957 回答
3

正如我在另一个答案的评论中所说,对 ref 参数的需求是代码异味。首先,如果你在一个方法中这样做,你就打破了单一责任原则,但更重要的是,代码只能在你的继承层次结构中重用。

这里有一个模式可以推导出来:

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; }
    }
}
于 2009-04-24T18:16:49.350 回答
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;
    }
}

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

于 2009-04-24T17:55:24.923 回答