错误CS0133:将函数的结果赋值给C#.net中的const

时间:2010-05-26 20:21:24

标签: c# syntax pinvoke

尝试整理范围并避免可能多次调用RegisterWindowMessage 目前有一个类使用以下成员

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

private int m_message = RegisterWindowMessage("MY_MSG"); 

由于我们只有一个实例,这似乎没问题,但认为使用它会更整洁。根据我的基本C#理解,这应该调用RegisterWindowMessage并将结果赋值给int并且不允许它更改。

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

然而,尝试这样做会导致

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

所以现在我很困惑,这是否意味着每次m_message被使用时都会分配和调用函数,是否还缺少其他内容?

3 个答案:

答案 0 :(得分:7)

const字段必须是编译时常量。如果您只想要在初始分配 1 后的执行时间内不会改变的内容,请将其设为只读:

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

请注意,我已将其设为静态,const是隐式的。这意味着RegisterWindowMessage只会为此AppDomain调用一次,这是我认为您想要的。

编辑:汉斯是对的,你应该检查返回值。您可以在第一次使用它时或者在初始化类型时执行此操作 - 通常,类型初始化程序抛出异常是个坏主意,但您应该看到影响是什么。


1 严格地说,可以在声明或静态构造函数中指定静态只读字段;可以在声明或任何实例构造函数中分配实例只读字段。它可以分配多次,通常没用,但偶尔也可以。

答案 1 :(得分:3)

这里有另一个考虑因素。 RegisterWindowMessage()可能会失败,您真的需要检查它。使用0会在出现问题时返回,否则很难诊断出来。

直接在readonly声明中将其初始化。您可以使用静态构造函数。问题是异常消息将隐藏在InnerException中。有点可以,因为失败将是罕见的。

最好的解决方案是一个懒惰地调用API的静态属性getter:

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;
  }
}

如果可以从不同的线程调用,则使用众所周知的锁定模式。

答案 2 :(得分:1)

要添加Hans给出的答案,你可以做的不仅仅是抛出一个空的Win32Exception。这适用于使用GetLastError的任何API调用:

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

if (m_message == 0)
    throw new Win32Exception(Marshal.GetLastWin32Error());

这将产生更具信息性的例外。