错误CS0133:将函数的结果分配给C#net中的常量
正在尝试整理作用域并避免可能多次调用RegisterWindowMessage。错误CS0133:将函数的结果分配给C#net中的常量,c#,syntax,pinvoke,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"); 因为
当前有一个类与以下成员一起使用一次
[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
时都会分配和调用函数,是否还缺少其他内容?Aconst
字段必须是编译时常量。如果您只是想要在初始赋值1后执行时不会更改的内容,请将其设置为只读:
private static readonly int Message = RegisterWindowMessage("MY_MSG");
请注意,我已经创建了这个static,它const
是隐式的。这意味着对于这个AppDomain,RegisterWindowMessage
将只被调用一次,这是我认为您想要的
编辑:Hans是对的,您应该检查返回值。您可以在第一次使用它时,或者在初始化类型时执行此操作—通常情况下,类型初始值设定项引发异常是个坏主意,但您应该了解其影响
1严格来说,可以在声明或静态构造函数中指定静态只读字段;可以在声明或任何实例构造函数中指定实例只读字段。它可以被多次赋值,这通常是没有用的,但偶尔也会被赋值。一个
const
字段必须是一个编译时常量。如果您只是想要在初始赋值1后执行时不会更改的内容,请将其设置为只读:
private static readonly int Message = RegisterWindowMessage("MY_MSG");
请注意,我已经创建了这个static,它const
是隐式的。这意味着对于这个AppDomain,RegisterWindowMessage
将只被调用一次,这是我认为您想要的
编辑:Hans是对的,您应该检查返回值。您可以在第一次使用它时,或者在初始化类型时执行此操作—通常情况下,类型初始值设定项引发异常是个坏主意,但您应该了解其影响
1严格来说,可以在声明或静态构造函数中指定静态只读字段;可以在声明或任何实例构造函数中指定实例只读字段。它可以被分配多次,这通常是没有用的,但可以偶尔分配。这里还有另一个考虑因素。RegisterWindowMessage()可能会失败,您确实需要对此进行检查。如果在出现问题时使用它返回的0,则很难进行其他诊断 这将直接在只读声明中对其进行初始化。您可以改用静态构造函数。问题是异常消息将被隐藏在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;
}
}
如果可能从不同的线程调用,请使用众所周知的锁定模式。这里还有另一个需要考虑的问题。RegisterWindowMessage()可能会失败,您确实需要对此进行检查。如果在出现问题时使用它返回的0,则很难进行其他诊断 这将直接在只读声明中对其进行初始化。您可以改用静态构造函数。问题是异常消息将被隐藏在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;
}
}
如果可能从不同线程调用,请使用众所周知的锁定模式。要补充Hans给出的答案,您可以做得比简单地抛出一个空的Win32Exception更好。这适用于使用GetLastError的任何API调用:
[DllImport("user32.dll", SetLastError = true)]
extern static int RegisterWindowMessage(string lpString);
if (m_message == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
这将产生一个信息更丰富的异常。为了补充Hans给出的答案,您可以做得比简单地抛出一个空的Win32Exception更好。这适用于使用GetLastError的任何API调用:
[DllImport("user32.dll", SetLastError = true)]
extern static int RegisterWindowMessage(string lpString);
if (m_message == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
这将产生一个信息更丰富的异常。请参见“这不正常,必须检查Windows API函数调用是否失败”。这不正常,必须检查Windows API函数调用是否失败。Hans是正确的。我不得不思考为什么我认为情况并非如此。如果未在p/invoke声明中指定SetLastError=true,封送处理程序将不会调用GetLastError,封送处理程序将返回0,这将导致异常消息为“操作已成功完成”。通过在Win32Exception构造函数中指定Marshal.GetLastWin32Error,实际上是在提醒自己需要将SetLastError=true添加到声明中。也许我是唯一需要提醒的人。汉斯是对的。我不得不思考为什么我认为情况并非如此。如果未在p/invoke声明中指定SetLastError=true,封送处理程序将不会调用GetLastError,封送处理程序将返回0,这将导致异常消息为“操作已成功完成”。通过在Win32Exception构造函数中指定Marshal.GetLastWin32Error,实际上是在提醒自己需要将SetLastError=true添加到声明中。也许我是唯一一个需要这样提醒的人。谢谢你在考虑可能的错误情况时提供的额外提示。谢谢你在考虑可能的错误情况时提供的额外提示。