Ошибка CS0133: назначение результата функции для const в C # .net - PullRequest
1 голос
/ 27 мая 2010

Попытка привести в порядок область видимости и избежать возможных множественных вызовов 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 ]

7 голосов
/ 27 мая 2010
Поле

A const должно быть константой времени компиляции . Если вы просто хотите что-то, что не изменится во время выполнения после первоначального назначения 1 , сделайте это только для чтения:

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

Обратите внимание, что я сделал это статическим, что const неявно. Это означает, что RegisterWindowMessage будет вызываться только один раз для этого AppDomain, что, я думаю, вам нужно.

РЕДАКТИРОВАТЬ: Ганс прав, вы должны проверить возвращаемое значение. Вы можете сделать это либо при первом его использовании, либо при инициализации типа - обычно инициализаторам типов не рекомендуется генерировать исключения, но вы должны увидеть, как это повлияет.


1 Строго говоря, статическое поле только для чтения может быть назначено в объявлении или в статическом конструкторе; Поле экземпляра только для чтения может быть назначено в объявлении или в любом конструкторе экземпляра. Его можно назначать несколько раз, что обычно не полезно, но может быть только время от времени.

3 голосов
/ 27 мая 2010

Здесь есть еще одно соображение.RegisterWindowMessage () может завершиться ошибкой, вам действительно нужно проверить это.Использование 0 возвращает, когда что-то не так, будет ужасно трудно диагностировать иначе.

Это выбивает инициализацию непосредственно в объявлении только для чтения.Вместо этого вы можете использовать статический конструктор.Проблема в том, что сообщение об исключении будет скрыто в InnerException.Вроде хорошо, возможно, так как сбой будет редким.

Лучшее решение - средство получения статических свойств, которое лениво вызывает 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;
  }
}

Используйте известные шаблоны блокировки, если это можно вызватьразные темы.

1 голос
/ 27 мая 2010

Чтобы добавить к ответу, который дал Ганс, вы можете сделать лучше, чем просто выбросить пустое Win32Exception. Это относится к любому вызову API, который использует GetLastError:

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

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

Это приведет к более информативному исключению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...