【问题标题】:"Specified cast is not valid" only on release build from MS build“指定的演员表无效”仅在 MS 版本的发布版本中
【发布时间】:2013-01-09 16:08:30
【问题描述】:

当仅从 MSBuild 4.0 进行发布构建时,我收到“指定的强制转换无效”有效。我使用 Visual Studio 2012 的发布版本对此进行了测试,但没有遇到此问题。我还使用 MSBuild 4.0 的调试版本对此进行了测试,但没有遇到此问题。

例外:

代码

    public abstract class CachedSessionBase : ISessionObject
{
    protected Dictionary<MethodBase, Object> _getAndSetCache = new Dictionary<MethodBase, object>();

    protected TResult SetAndGet<TResult>(ObjectFactory factory, Func<TResult> func)
    {
        StackTrace stackTrace = new StackTrace();
        var methodBase = stackTrace.GetFrame(1).GetMethod();

        if (!_getAndSetCache.ContainsKey(methodBase))
        {
            _getAndSetCache[methodBase] = func.Invoke();
        }

        return (TResult)_getAndSetCache[methodBase];
    }

在这一行抛出错误

return (TResult)_getAndSetCache[methodBase];

【问题讨论】:

  • 我会添加一些跟踪行来仔细检查来自_getAndSetCache[methodBase] 的任何内容实际上是TResult 类型。在发布配置(启用优化)中,如果方法被内联,堆栈框架可能会改变。 stackTrace.GetFrame(1).GetMethod()
  • 澄清一下,我认为问题在于stackTrace.GetFrame(1).GetMethod() 在发布时返回的内容与调试时不同。我建议不要使用它,但不能提供任何替代方案。
  • 可以在返回之前记录下对象的类型吗?
  • StackTrace 永远不应该在生产代码中使用。唯一罕见的例外是错误处理/日志记录,它试图对发生的事情进行更智能的分析(即使那样我也会质疑正在做的事情的有效性)

标签: c# .net visual-studio msbuild il


【解决方案1】:

调用堆栈可能与您预期的不同。您的方法可能会被内联,然后GetFrame(1) 正在检索调用者的调用者。当从字典中检索到值时,它属于不同的类型,因为它用于不同的方法。

您可以尝试将属性[MethodImpl(MethodImplOptions.NoInlining] 添加到SetAndGet 以防止该方法的内联优化。

【讨论】:

  • +1 点。肯定是发布配置中的代码优化器导致了这种情况。
  • 试过这个答案。虽然在正确的轨道上并且非常接近,但在我的场景中不起作用。我正在使用 stackTrace.GetFrame(1).GetMethod() 来了解调用者是谁。调用者函数正在内联优化。调用者将需要实现 [MethodImpl(MethodImplOptions.NoInlining]。没有办法强制调用者这样做,所以我将不得不考虑另一种解决方案。
  • @Anish 你真的应该。将StackTrace 用于非调试的东西通常是个坏主意。
  • 谢谢。我会尝试不同的模式。
【解决方案2】:

我在运行nuget pack 时遇到了同样的问题,它调用了

MSBuild 自动检测:使用 msbuild 版本 '15.0'...

但问题通过运行dotnet pack 解决了

适用于 .NET Core 的 Microsoft (R) Build Engine 版本 15.3.409.57025

【讨论】:

  • 对于所有在 mac 上使用 .net core 的人来说,这是正确的答案。非常感谢斯蒂芬
猜你喜欢
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 2014-11-17
相关资源
最近更新 更多