10

以下代码编译时出现警告和智能感知错误:

ref class Test {
    initonly static TimeSpan Delay = TimeSpan(1,1,1); 

    Test() {
        long long ticks = Delay.Ticks; // << problem
    }
};

问题是:

  • 警告 C4395:“System::TimeSpan::Ticks::get”:将在 initonly 数据成员“Test::Delay”的副本上调用成员函数
  • IntelliSense:不允许获取 initonly 字段的地址

如何正确访问 Ticks?

4

2 回答 2

13

嗯,这是相当大的失败鲸鱼。警告是准确的,编译器对 TimeSpan::Tick 属性获取器的了解不够。它不能确保 getter 不做任何可能改变结构值的事情,从而使initonly合同无效。它通过复制结构并警告它来解决它,因为这可能是一个性能问题。这有点笨拙,其他托管编译器制作副本而不说任何内容。我只是#pragma warning(disable:4395)在它前面放了一个,所以警告被抑制了。

IntelliSense 错误仅在我在 VS2012 中尝试时出现。那是一个错误。您可以在 connect.microsoft.com 上报告它。

考虑到痛苦并且这似乎是一个私人班级成员,我只会放弃initonly以取得成功。如果这不是可取的,那么您可以用属性包装该字段,故意创建副本,从而摆脱这两个问题,如下所示:

ref class Test {
    initonly static TimeSpan _delay = TimeSpan(1,1,1); 
    static property TimeSpan Delay { 
        TimeSpan get() { return _delay; }
    }

    Test() {
        long long ticks = Delay.Ticks;
    }
};

抖动优化器将摆脱它,所以不用担心开销。

于 2012-12-12T03:01:47.200 回答
0

感谢 Hans Passant 的解释,我现在更好地理解了上下文

我刚刚遇到了同样的问题。

我的解决方案是

  • 将 'initonly' 替换为 'const'
  • 访问时,只要把 const 扔掉,就不会留下任何错误/警告

也许这不是“最先进的”编码,但它工作正常,请参见此处 (VisualStudio2017 仍然暴露此行为/问题)

于 2018-09-03T11:27:14.117 回答