Почему мне разрешено определять SendCompletedEventHandler для объекта поля stati c только для чтения, внутри не статичного c конструктора? - PullRequest
2 голосов
/ 28 февраля 2020
private static readonly SmtpClient SmtpClient = new SmtpClient (...)


public Constructor()
{
   SmtpClient.SendCompleted += new SendCompletedEventHandler(SendCompletedMethod);
   // Above is allowed and legal. Why, when the field is marked as static read-only?
}

Есть идеи, почему это разрешено? Я действительно смущен. Кроме того, это приведет к ошибке, если конструктор когда-либо будет выполнен дважды.

1 Ответ

2 голосов
/ 28 февраля 2020

Поле доступно только для чтения, что означает, что вы не можете изменить поле , но поскольку SmtpClient является ссылочным типом, поле просто ссылка . Итак: вы не можете изменить ссылку - вы можете , однако, делать все, что вы хотите с объектом за ссылкой, если этот тип является изменяемым, что это явно так. Это ничем не отличается от:

class Foo
{
    public string Bar {get;set;}
}
static readonly Foo s_foo = new Foo();
//... later
s_foo.Bar = "we changed it";

Пометка поля как readonly не заставляет компилятор обрабатывать базовый тип как неизменяемый (если мы не говорим о типах значений, которые имеют разные правила). Это не может , потому что любой метод (включая методы получения свойств, которые являются просто методами с определенной формой) может изменить внутреннее состояние, не обращая на это внимания вызывающего.


Примечание что для значений-типов существует понятие readonly struct; в сценарии нам дается гарантия того, что методы не будут изменять внутреннее состояние, что позволяет компилятору и среде выполнения принимать лучшие решения о том, как применять readonly к полям, которые являются типами значений (и, таким образом, поле является содержимым); без readonly struct компилятор делает защитную копию типа значения перед каждым вызовом метода, чтобы предотвратить изменение поля; с readonly struct это не так, поскольку доверяет типу, который не изменяется. Это , а не , однако я говорю "переключиться на типы значений"; значения-типы предназначены для очень конкретных c целей, и их не следует использовать случайно, не понимая всех последствий.

...