2017-02-24 59 views
2

我有一个属性,哪个getter应该只在第一次加载它的值。第二次返回加载的值,而无需再次加载它:加载属性延迟加载

private Object _MemberValue; 

public Object MemberValue 
{ 
    get 
    { 
     if(_MemberValue == null) 
     { 
      _MemberValue = LoadMember(); 
     } 

     return _MemberValue; 
    } 
} 

在VB.NET中存在Static关键字。有了它,你不必声明一个班级成员。

Public Property MemberValue as Object 
    Get 
     Static value as Object = Nothing 

     If (value is Nothing) Then 
      value = LoadMember() 
     End If 

     Return value 
    End Get 
End Property 

在C#没有这样的关键字。

有没有更好的C#实现这个问题或其他模式?

+2

[推荐使用的原因'Static'不好读。(http://stackoverflow.com/a/7475348/993547) –

+0

查看懒惰对象 – Nkosi

+2

你的第一个片段btw有什么问题? –

回答

7

有没有更好的C#实现这个问题或其他模式?

可能不是。如果您愿意,您可以使用Lazy<T>作为替换,但基本上与第一个示例相同。在VB.NET has some serious drawbacks中使用Static,所以我不会以任何方式使用它。

如果你喜欢Lazy<T>,这是我会用什么:

private Lazy<object> _MemberLazy = new Lazy<object>(LoadMember); 

public object MemberValue 
{ 
    get 
    { 
     return _MemberLazy.Value; 
    } 
} 
+3

啊,我想我应该downvote,因为我试图帮助你误解VB.NET的'静态'.. –

+3

有人滥用这个系统,有一个upvote。 –

+1

有人在这个问题上有一个领域的一天。显然不喜欢这个问题或答案。虽然我的+1。 – Bugs

4

你最初的方法似乎是合适的,我从来没有理由做一些不同的事情。这就是说,如果你的目标是避免一个可能被写入到getter之外的类级别字段,可能像this这样的工作。还有许多其他ReadOnly,WriteOnce,SetOnce实现也可以类似地工作。

ReadOnlyField.cs

public class ReadOnlyField<T> 
{ 
    private bool _frozen; 
    private T _value; 

    public T Value 
    { 
     get { return _value; } 
     set 
     { 
      if (_frozen) 
       throw new InvalidOperationException(); 

      _value = value; 
     } 
    } 

    public void Freeze() 
    { 
     _frozen = true; 
    } 
} 

YourObject.cs

public class YourObject 
{ 
    private readonly ReadOnlyField<object> _someMember; 

    public object MemberValue 
    { 
     get 
     { 
      if(_someMember.Value == null) 
      { 
       _someMember.Value = LoadMember(); 
       _someMember.Freeze(); 
      } 

      return _someMember.Value; 
     } 
    } 

    public YourObject() 
    { 
     _someMember = new ReadOnlyField<object>(); 
    } 
} 

它并不完美。不像你的VB.Net例子; getter之外的代码可能会先写入字段,但至少可以防止在调用Freeze后被覆盖。

+2

我没有投票,但我会认为这是因为它似乎就像复制懒惰一样,它开始于.NET 4 –

+0

@the_lotus懒惰有其自身的局限性。这个问题不明确,也不现实。加载可能是其他变量的功能,你可能需要刷新UI或其他事件.. – 2017-02-24 14:35:13