我有以下结构:
struct someData
{
public bool check;
public string text;
}
...
someData sd = new someData(){ check = true, text = "just testing" };
Cache.Insert(cacheInd, sd, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(90));
然后在代码中,我想从缓存中检索数据,但我得到一个 InvalidCastException:
if (Cache[cacheInd] != null)
{
someData sd = (someData)Cache[cacheInd];//Error here
如果我尝试这个:
someData sd = Cache[cacheInd] as someData;
我得到:
The as operator must be used with a reference type or nullable type ('ASP._dev_pull_aspx.someData' is a non-nullable value type)
有什么解决办法吗?
这就是我正在做的事情:
- 加载页面(尚未缓存)-> 一切正常
- 重新加载它(缓存)-> 一切都很好
- 更改与页面其他位置不相关的代码 -> 获取异常
- 回收缓存修复它(直到我再次更改代码)
注意:感谢 MethodMan 和 Michael Humelsine 对 as
失败的解释 - Why can't I use the as keyword for a struct? ,但未能执行强制转换仍不清楚,特别是因为它在大多数情况下都有效。
最佳答案
看起来您得到了 2 个不同类型,其类型与重新编译页面的结果相同,因此尽管名称/结构非常相似,但您无法将一种类型转换为另一种类型。
为什么:
- 在 .Net 中,类型标识包括全名和程序集标识(名称),例如“System.Int32 from System.dll v4.0.0.0”。
- 更改 ASPX/CSHTML 页面会生成具有随机名称的新程序集,但不会触发应用程序域的回收(特别是在调试配置中),直到“动态编译程序集的数量”达到相对较高的阈值被点击(手头没有好的链接,请搜索。即 this one 讨论 ASPX 与 Razor 之间的差异)
如果比较整个 Type
对象(typeof(someData)
与 Cache[cacheInd].GetType()
- 其中一个属性会有所不同,即 Type.FullName
可能是候选属性。
我希望这些类型看起来类似于以下内容(其程序集名称有所不同):
- {
ASP._dev_pull_aspx.someData
来自“ASP._dev_pull_aspx._3333.dll” - {
ASP._dev_pull_aspx.someData
来自“ASP._dev_pull_aspx._7777.dll”
要解决此问题,您应该将您关心的类型从页面移动到已编译的程序集,或者接受有时类型不匹配并重新启动应用程序域的事实。通常,重建项目或 web.config 更改会触发应用程序域回收,因为它是回收触发器的一部分以及各个页面的重新编译次数。
注释:
- 将
struct someData
更改为class someData
仍会重现该错误,但您可能会看到更详细的消息,因为类型仍然会有所不同 - 此类错误的其他常见情况是由于代码共享(如将相同的源文件包含到多个项目中)而在多个程序集/命名空间中复制相同类型以及使用多个版本相同的强命名程序集。
关于c# - 当类型看起来相同时,从缓存获取结构失败并出现强制转换错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28096704/