我有一个用于图片上传的洪水限制器:
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;
当您使用一个类时,您会从字典中获得引用的副本。仍然只有一个对象,但有两个对它的引用。
注意:术语通过引用 和通过值 指的是参数的传递方式。参数始终按值传递,无论它是结构还是类,除非您使用 ref
或 out
关键字。按值传递的是结构的副本或对象引用的副本。
关于c# - Struct 不缓存,但 Class 缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32442000/