Udostępnij za pośrednictwem


Warunkowa ocena ciągu w metodach debugowania

Często używa się ciągów interpolowanych jako komunikatów asercyjnych, na przykład:

Debug.Assert(result != x, $"Unexpected result {result}");

Jednak w poprzednich wersjach powoduje to utworzenie ciągu dla komunikatu, w tym wyniku formatowania, przy każdym wywołaniu, nawet jeśli warunek to true. Typowym zastosowaniem asercj jest to, że chodzi o warunek, który zawsze powinien być prawdziwy.

Język C# 10 dodaje obsługę lepszej interpolacji ciągów, w tym możliwość kierowania niestandardowych "procedur obsługi" oprócz ciągów. Na platformie .NET 6 klasa Debug ma nowe przeciążenia Assert, WriteIf i WriteLineIf, które wykorzystują tę funkcję do warunkowego oceniania elementów formatowania interpolowanych ciągów tylko wtedy, gdy jest wymagany komunikat. Kompilator języka C# preferuje te nowe przeciążenia. Jeśli elementy formatowania zmieniały stan, a program polegał na tych mutacjach, aby były widoczne, nawet jeśli założenie nie zostało wykonane, można zaobserwować różnicę w zachowaniu.

Poprzednie zachowanie

W poniższym kodzie r.ToString() zawsze będzie wywoływany.

Debug.Assert(true, $"{r.ToString()}");

Nowe zachowanie

W poniższym kodzie r.ToString() nigdy nie zostanie wywołany, ponieważ komunikat jest potrzebny tylko wtedy, gdy spełniony jest warunek false.

Debug.Assert(true, $"{r.ToString()}");

Wersja wprowadzona

6.0 RC 1

Typ zmiany przełamującej

Ta zmiana może mieć wpływ na zgodność źródła .

Przyczyna zmiany

Ta zmiana została wprowadzona w celu zwiększenia wydajności.

Ciągi interpolowane używane z metodami Debug nie powinny mutować stanu udostępnionego. (Te metody są uzależnione od stałej kompilacji DEBUG.) Jeśli z jakiegoś powodu ważne jest utrzymanie dotychczasowego zachowania, dodaj rzutowanie (string) przed ciągiem interpolowanym. Rzutowanie wymusza powiązanie kompilatora z istniejącym przeciążeniem i gwarantuje, że ciąg jest zawsze zmaterializowany.

Interfejsy API, których dotyczy problem