Patrick Skelton Ответов: 2

Почему я всегда вижу начальное значение статической переменной?


У меня есть какое-то странное поведение в коде, которое, казалось бы, настолько просто, что у меня закончились места для поиска ошибки.

В приведенном ниже классе функция RunStepNormally() призванный. Пока все хорошо.

Затем я звоню SomeClass.InitiateTimeSeek(), что подтверждается попаданием точки останова. Пока все идет хорошо.

Проблема возникает в следующем цикле. В RunStep(), значение _runningRealTime является истинным, даже если он был явно установлен в false в InitiateTimeSeek().

Если я изменю значение инициализации _runningRealTime ложному, то оно остается при ложном. Другими словами, в RunStep() Я всегда вижу какую-то ценность _runningRealTime инициализируется и никогда не видит ничего другого.

public abstract class SomeClass<T>
{
	public void RunStep()
	{
		if( _runningRealTime )
			RunStepNormally();
		else
			RunStepTimeSkipActive();
	}

	public static void InitiateTimeSeek()
	{
		_runningRealTime = false;
	}

	public static void CancelTimeSeek()
	{
		_runningRealTime = true;
	}

	public void RunStepNormally() {}

	public void RunStepTimeSkipActive() {}


	private static bool _runningRealTime = true;
}


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

Что я уже пробовал:

Моей первой мыслью было, что новые экземпляры класса создаются неоднократно, но точка останова в конструкторе (не показана) попадает только один раз, как я и ожидал.

2 Ответов

Рейтинг:
4

Richard Deeming

Ваш класс является универсальным. У вас будет отдельная копия статических полей для каждого параметра универсального типа. Если ты позвонишь SomeClass<Foo>.InitiateTimeSeek(), это не повлияет на SomeClass<Bar>._runningRealTime поле, даже если существует отношение наследования между параметрами типа.

Статические поля в универсальных классах | онлайн-компилятор C# | .NET Fiddle[^]


Patrick Skelton

Я только что открыл для себя этот довольно очевидный факт. Я обнаружил, что инициализация для статической переменной была поражена более одного раза, что именно то, что вы ожидали бы, учитывая то, что вы указали.

Ключ должен был быть в довольно ужасном коде, который я использовал для вызова статических функций: SessionStateBase<ISession>.InitiateTimeSeek();

Я переместил переменную в класс, который не является универсальным и на самом деле является гораздо более естественным домом. Теперь все работает нормально.

Это научит меня делать комментарии типа "этот класс-абстрактный общий класс, хотя я изо всех сил пытаюсь понять, почему это должно быть уместно"!

Спасибо за ответ, Ричард.

Рейтинг:
1

OriginalGriff

Ваш код не будет компилироваться для меня:

Error	CS0127	Since 'FrmMain.SomeClass.RunStep()' returns void, a return keyword must not be followed by an object expression	OneOffJobs	D:\Documents\AA Backed Up\My Projects\OneOffJobs\OneOffJobs\FrmMain.cs	113	Active
То, что работает .Чистая 4.72 на VS2019

Так... если код не компилируется, то то, что выполняется, может не соответствовать этому коду.
Либо вы слишком сильно сократили образец кода, чтобы показать проблему, либо ваш фактический код работает против устаревшего класса.


Patrick Skelton

Так жаль! Я действительно неуклюже вырезал код. Я исправил его и добавил несколько строк, чтобы сделать его более полным. Я также удалил "асинхронные" биты, потому что они просто сбивали с толку. Я должен также указать, что этот класс является абстрактным родовым классом, хотя я изо всех сил пытаюсь понять, почему это должно быть уместно (точка зрения, которую я могу в конечном итоге отказаться, когда исчерпаю все другие возможности).

OriginalGriff

Это просто: каждый универсальный тип получает свою собственную статическую переменную, они не взаимодействуют. (Что имеет смысл, если вы подумаете об этом: List<int> - Это не тот же класс, что и List<string>, и они не могут быть приведены друг к другу, так зачем им что-то делиться?)

Самое простое решение - создать другой - не универсальный-абстрактный базовый класс, из которого происходит SomeClass, и иметь его, определяющий статическую переменную.