c# - Struct 不缓存,但 Class 缓存

标签 c# asp.net class caching struct

我有一个用于图片上传的洪水限制器:

public class FloodLimiter
{
    public static void OnImageUploaded(string ipAddress, int sizeBytes)
    {
        var dict = GetImageUploadFloodLimitDict();
        if (!dict.ContainsKey(ipAddress))
        {
            dict.Add(ipAddress, new ImageUploadLimits());
        }
        dict[ipAddress].OnFileUploaded(sizeBytes);
    }

    public static bool CanUploadImages(string ipAddress)
    {
        var dict = GetImageUploadFloodLimitDict();
        if (!dict.ContainsKey(ipAddress)) return true;
        return dict[ipAddress].BelowLimits;
    }

    private static readonly object FloodLimitLock = new object();
    /// <summary>
    /// Dictionary of IP's, and total images uploaded + total image size uploaded
    /// </summary>
    private static Dictionary<string, ImageUploadLimits> GetImageUploadFloodLimitDict()
    {
        const string cacheIndex = Settings.CachePrefix + "ImageUploadFloodLimiter";
        var context = HttpContext.Current;
        if (context.Cache[cacheIndex] == null)
        {
            lock (FloodLimitLock)
            {
                if (context.Cache[cacheIndex] == null)
                {
                    var dict = new Dictionary<string, ImageUploadLimits>();
                    context.Cache.Add(cacheIndex, dict, null, DateTime.Now.AddMinutes(Settings.ImageUpload.FloodLimitRecycleMinutes), Cache.NoSlidingExpiration, CacheItemPriority.AboveNormal, null);
                }
            }
        }
        return (Dictionary<string, ImageUploadLimits>)context.Cache[cacheIndex];
    }
}

如果 ImageUploadLimits 定义为:

private struct ImageUploadLimits
{
    private int _totalImagesUploaded;
    private int _totalBytesUploaded;
    public bool BelowLimits { get {
        return _totalImagesUploaded < Settings.ImageUpload.MaximumImagesCanUploadInPeriod && _totalBytesUploaded < (Settings.ImageUpload.MaximumImageUploadMbInPeriod * 1000000);
    }}

    public void OnFileUploaded(int sizeBytes)
    {
        _totalImagesUploaded ++;
        _totalBytesUploaded += sizeBytes;
    }
}

缓存永远不会更新(它总是返回 1 张上传的图片)。

如果我将 ImageUploadLimits 定义为:

private class ImageUploadLimits
{
    private int _totalImagesUploaded;
    private int _totalBytesUploaded;
    public bool BelowLimits { get {
        return _totalImagesUploaded < Settings.ImageUpload.MaximumImagesCanUploadInPeriod && _totalBytesUploaded < (Settings.ImageUpload.MaximumImageUploadMbInPeriod * 1000000);
    }}

    public void OnFileUploaded(int sizeBytes)
    {
        _totalImagesUploaded++;
        _totalBytesUploaded += sizeBytes;
    }
}

它工作得很好!

为什么 struct 版本没有缓存?这与 Structs 被 Val 传递和 Classes 被 Ref 传递有关吗?

最佳答案

当您从字典中读取结构时,您会得到该结构的副本。 OnFileUploaded 方法对值所做的更改只会影响副本,不会影响字典中的原始内容。

如果使用结构体,则需要将副本写回字典:

ImageUploadLimits copy = dict[ipAddress];
copy.OnFileUploaded(sizeBytes);
dict[ipAddress] = copy;

当您使用一个类时,您会从字典中获得引用的副本。仍然只有一个对象,但有两个对它的引用。


注意:术语通过引用通过值 指的是参数的传递方式。参数始终按值传递,无论它是结构还是类,除非您使用 refout 关键字。按值传递的是结构的副本或对象引用的副本。

关于c# - Struct 不缓存,但 Class 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32442000/

相关文章:

c# - 事件顺序背后的 SqlDataSource 代码

c# - 将数组传递给 SQL Server 存储过程

jquery - ASP.Net 4.5 Twitter Bootstrap 和客户端验证

c# - .NET 中是否有一种功能,方法可以通过该功能确定哪个类调用了它

asp.net - GridView 中 TemplateField 上的 header

c++ - 为什么/什么时候我想在不定义类对象的情况下使用类数据成员?

java - 如何在 Android 应用程序的外部类中使用 Java 加载此文本文件?

c# - 获取通用的自定义属性

c# - 按日期值排序列表

c++: std::tr1::shared_ptr 从这个