代码之家  ›  专栏  ›  技术社区  ›  Greg Domjan

错误CS0133:将函数的结果赋给C.NET中的常量

  •  1
  • Greg Domjan  · 技术社区  · 15 年前

    试图整理范围并避免可能多次调用RegisterWindowMessage。
    当前有一个类与以下成员一起使用一次

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern int RegisterWindowMessage(string lpString);
    
    private int m_message = RegisterWindowMessage("MY_MSG"); 
    

    因为我们只有一个实例,所以这似乎可以,但认为使用起来会更整洁。根据我的基本理解,这应该调用registerwindowmessage并将结果分配给int,而不允许它更改。

    private const int message = RegisterWindowMessage("MY_MSG"); 
    

    但是,尝试这样做会导致

    error CS0133: The expression being assigned to 'someclass.messageEvent' must be constant
    

    所以现在我很困惑,这是否意味着每次都在分配和调用函数? m_message 以前用过,还有什么东西不见了吗?

    3 回复  |  直到 15 年前
        1
  •  7
  •   Jon Skeet    15 年前

    const 字段必须是 编译器常量 . 如果您只是想要一些在初始分配后执行时不会改变的东西 ,使其只读:

    private static readonly int Message = RegisterWindowMessage("MY_MSG");
    

    注意,我做了这个静态的,它 康斯特 是隐含的。这意味着 RegisterWindowMessage 只会为此AppDomain调用一次,这是我认为您需要的。

    编辑:汉斯是对的,你应该检查返回值。您可以在第一次使用它时,或者当类型初始化时,这样做——通常类型初始值设定项抛出异常是一个坏主意,但是您应该看看影响是什么。


    严格来说,静态只读字段可以在声明或静态构造函数中分配;实例只读字段可以在声明或任何实例构造函数中分配。它 可以 多次分配,即 通常 不是很有用,只是偶尔有用。

        2
  •  3
  •   Hans Passant    15 年前

    这里还有一个考虑。registerWindowMessage()可能会失败,您 真正地 需要检查一下。如果使用它返回的0,那么当出现问题时,很难进行诊断。

    这将直接在readonly声明中取消初始化。可以改用静态构造函数。问题是异常消息将隐藏在一个innerException中。也许可以,因为失败是罕见的。

    最好的解决方案是一个静态属性getter,它可以延迟地调用API:

    private int m_message
    
    public static int message {
      get {
        if (m_message == 0) {
          m_message = RegisterWindowMessage("blah");
          if (m_message == 0) throw new Win32Exception();
        }
        return m_message;
      }
    }
    

    如果可以从不同的线程调用,请使用已知的锁定模式。

        3
  •  1
  •   Tergiver    15 年前

    为了增加汉斯给出的答案,您可以做得比简单地抛出一个空的win32exception更好。这适用于使用GetLastError的任何API调用:

    [DllImport("user32.dll", SetLastError = true)]
    extern static int RegisterWindowMessage(string lpString);
    
    if (m_message == 0)
        throw new Win32Exception(Marshal.GetLastWin32Error());
    

    这将产生一个信息更丰富的例外。