Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
错误CS0133:将函数的结果分配给C#net中的常量_C#_Syntax_Pinvoke - Fatal编程技术网

错误CS0133:将函数的结果分配给C#net中的常量

错误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"); 因为

正在尝试整理作用域并避免可能多次调用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
时都会分配和调用函数,是否还缺少其他内容?

A
const
字段必须是编译时常量。如果您只是想要在初始赋值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添加到声明中。也许我是唯一一个需要这样提醒的人。谢谢你在考虑可能的错误情况时提供的额外提示。谢谢你在考虑可能的错误情况时提供的额外提示。