为什么使用System.Runtime.Caching或System.Web.Caching Vs静态变量?

sfs*_*fsr 27 .net c# asp.net static caching

长时间听众 - 第一次来电.我希望得到一些建议.我一直在阅读.net中的缓存 - 包括System.Web.Caching和System.Runtime.Caching.我想知道我可以获得什么额外的好处与简单地创建一个带锁定的静态变量.我目前的(简单的)缓存方法是这样的:

public class Cache
{
    private static List<Category> _allCategories;
    private static readonly object _lockObject = new object();

    public static List<Category> AllCategories
    {
        get
        {
            lock (_lockObject)
            {
                if (_allCategories == null)
                {
                    _allCategories = //DB CALL TO POPULATE
                }
            }
            return _allCategories;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

除了到期(我不希望它到期)我不知道使用内置缓存的好处是什么.

也许对于不适用于我的更复杂的缓存方案有好处 - 或者我可能只是缺少某些东西(这不是第一次).

那么,如果我想要一个永不过期的缓存,使用缓存有什么好处?静态变量不这样做吗?

Mig*_*elo 21

System.Runtime.Caching和System.Web.Caching具有自动过期控制,可以基于文件更改,SQL Server数据库更改,并且您可以实现自己的"更改提供程序".您甚至可以在缓存条目之间创建依赖关系.

请参阅此链接以了解有关System.Caching命名空间的更多信息:

http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx

我提到的所有功能都记录在链接中.

使用静态变量需要手动控制到期时间,并且您必须使用文件系统观察程序和缓存命名空间中提供的其他程序.

  • 我认为如果你不需要他们的服务,你不应该把自己绑在框架上.如果您不需要过期控制,也不需要缓存系统的其他服务,则不要使用它.但如果你需要,不要重新发明轮子.那当然是我的观点!有些人可能不同意. (3认同)
  • 哇 - 你们快点:)这是一个很好的观点.我可以在更复杂的情况下完全看到它的需要 - 但假设原始问题中的类别列表是固定列表(意味着变化非常罕见),我不希望它过期 - 我假设额外的开销需要保持过期控制实际上是使用静态变量的投票,因为在这种情况下它们会更高效.顺便说一句 - 我想进行这样的讨论,并希望深入研究这些类型的东西 - 我并不是想要顽固 - 只是在另一方面提出这个问题. (2认同)

Str*_*ior 20

首先,Xaqron提出了一个很好的观点,即你所谈论的内容可能不具备缓存的条件.它实际上只是一个懒惰的全局可访问变量.这很好:作为一个实用的程序员,没有必要向后弯曲以实现全面的缓存,而这并不是真正有益的.但是,如果您打算使用这种方法,那么您可能Lazy会让.NET 4完成繁重工作:

private static Lazy<IEnumerable<Category>> _allCategories
    = new Lazy<IEnumerable<Category>>(() => /* Db call to populate */);

public static IEnumerable<Category> AllCategories 
{ 
    get { return _allCategories.Value; } 
}
Run Code Online (Sandbox Code Playgroud)

我冒昧地改变了类型,IEnumerable<Category>以防止调用者认为他们可以添加到此列表中.

也就是说,无论何时访问公共静态成员,都会错失面向对象编程所提供的大量灵活性.我个人建议你:

  1. 将类重命名为CategoryRepository(或类似的东西),
  2. 使这个类实现一个ICategoryRepository接口,GetAllCategories()在接口上使用一个方法,和
  3. 将此接口构造符注入任何需要它的类.

这种方法使您可以对应该对所有类别执行操作的单元测试类进行单元测试,完全控制测试哪些"类别",而无需数据库调用.