代码之家  ›  专栏  ›  技术社区  ›  Timo Willemsen

“缓存”属性

  •  1
  • Timo Willemsen  · 技术社区  · 15 年前

    我有一个充满属性的类。当访问属性时,它从XDocument中读取一些值。

    public class Foo
    {
     private XDocument root;
    
     public Foo(Stream str)
     {
      root = XDocument.load(str);
     }
    
     public String Bar
     {
      get
      {
       return root.Element("bar").Value;
      }
     }
    
    }
    

    只是看起来有点开销,因为每次访问它都必须再次读取XDocument。我试着“缓存”这一点如下

    public String Bar
    {
     get
     {
      if(String.IsNullOrEmpty(this.Bar))
       return root.Element("bar").Value;
      else
       return this.Bar;
     }
    }
    

    4 回复  |  直到 15 年前
        1
  •  4
  •   Jon Skeet    15 年前

    正如“thelost”提到的,不要为每个属性都有一个字段。保留一个字典作为缓存,这样你就不用为没有访问过的属性支付任何费用。

    我建议你有一个方法,你可以提供检索实际值的机制。例如:

    public class Foo
    {
        private enum CacheKey
        {
            Bar, Baz, ...;
        }
    
        private readonly XDocument doc;
        private readonly Dictionary<CacheKey, string> cache;
    
        private string Fetch(CacheKey key, Func<XDocument, string> computation)
        {
            string result;
            if (!cache.TryGetValue(key, out result))
            {
                result = computation(doc);
                cache[key] = result;
            }
            return result;
        }
    
        public string Bar
        {
            get { return Fetch(CacheKey.Bar, doc => doc.Element("bar").Value); }
        }
    }
    

    这样每个属性最终都相当紧凑—它基本上表示了所涉及的缓存键,以及如何计算属性。如果您需要不同类型的属性,您可能希望缓存只有 TValue 作为 object ,并使 Fetch

    如果您在多个地方使用这种方法,您很可能希望创建一个泛型 ComputingCache 类以避免重复逻辑。

        2
  •  2
  •   thelost    15 年前

    未测试:

    enum MyProperties {
        Prop1,
        Prop2
    }
    
    // ...
    
    static class PropertyProvider {
        static Hashtable<MyProperties, Object> cache = new Hashtable<MyProperties, Object>();
        static Object getProperty(MyProperties prop) {
            if (!cache.ContainsKey(prop)) {
                cache.add(prop, "SOMETHING");
            }
    
            return cache[prop];
        }
    }
    
    // ...
    
    Object result = PropertyProvider.getProperty(MyProperties.Prop1);
    
        3
  •  2
  •   RQDQ    15 年前

    如果您使用的是.NET4.0,那么可以使用handy Lazy类。

    http://weblogs.asp.net/gunnarpeipman/archive/2009/05/19/net-framework-4-0-using-system-lazy-lt-t-gt.aspx

    如果您使用的是以前版本的框架,那么只需编写自己版本的Lazy类(并不特别复杂)。

        4
  •  1
  •   James Manning    15 年前

    懒惰的部分重要吗?如果没有,只需在同一时间填充所有属性(它们都可以是自动的),就完成了。我宁愿这样做,因为如果xml有问题,它会更快地失败。如果懒惰很重要,那么在.NET4中,你可以用懒惰来代替它们。