代码之家  ›  专栏  ›  技术社区  ›  dance2die

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

  •  0
  • dance2die  · 技术社区  · 16 年前

    :带有Resharper 4.1的Visual Studio 2008 SP1。净值3.5

    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 回复  |  直到 8 年前
        1
  •  13
  •   Adam Robinson    16 年前

    你的方法有缺陷。要采取这种方法,你需要 backingField ref 参数。

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

    然后呢 GetProperty ,通过 ref _ImagXpress ref _PdfXpress .

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

        2
  •  5
  •   dustyburwell    16 年前

    你的方法有缺陷。你的字段永远不会被设置为任何值。这 backingField 争论正在进行中 GetProperty<T> 方法,但这不会更新您传入的字段。您需要使用 ref 关键字附加到它像这样:

    private static T GetProperty<T>(ref T backingField, Func<T> factory)
    
        3
  •  3
  •   Michael Meadows    16 年前

    正如我在另一个答案的评论中所说,对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; }
        }
    }
    
        4
  •  1
  •   dustyburwell    16 年前

    要提出不同的解决方案:

    我想说,将逻辑封装到单独的方法中并不能节省很多。你在增加你的复杂性,却没有多大收获。我建议这样做:

    protected PdfXpress PdfXpress
    {
        get
        {
            if (_PdfXpress == null)
                _PdfXpress = PdfXpressSupport.Create();
    
            return _PdfXpress;
        }
    }
    
    protected ImagXpress ImagXpress
    {
        get
        {
            if (_ImagXpress == null)
                _ImagXpress = IMagXpressSupport.Create();
    
            return _ImagXpress;
        }
    }
    

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