如何正确访问c ++ / CLI initonly TimeSpan字段?

时间:2012-12-12 02:20:02

标签: .net visual-c++ .net-4.0 c++-cli

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

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?

2 个答案:

答案 0 :(得分:12)

嗯,那是非常重要的失败鲸鱼。警告是准确的,编译器对TimeSpan :: Tick属性getter知之甚少。它无法确保getter不会执行任何可能会更改结构值的内容,从而使 initonly 合同无效。它通过制作结构的副本并对其进行警告来解决它,因为这是一个可能的性能问题。这有点笨拙,其他托管编译器制作副本时没有说任何关于它的内容。我只是在它之前插入一个#pragma warning(disable:4395),以便警告被抑制。

只有在VS2012中尝试此操作时才会出现IntelliSense错误。那是一个错误。您可以在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;
    }
};

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

答案 1 :(得分:0)

感谢汉斯·帕桑(Hans Passant)的解释,我现在对上下文的理解要好得多

我遇到了同样的问题。

我的解决方法是

  • 将“ initonly”替换为“ const”
  • 访问时,只需将const抛弃,就不会留下任何错误/警告

也许这不是“最先进的”编码,但效果很好,请参见here (VisualStudio2017仍然会暴露这种行为/问题)