Как изготовить пустую строку в. NET? - PullRequest
5 голосов
/ 13 февраля 2020

Я написал фрагмент оптимизированного кода, который содержит специальные случаи для null и пустые строки. Я сейчас пытаюсь написать модульный тест для этого кода. Для этого мне нужны два пустых (нулевых) строковых объекта, которые являются разными объектами. Например:

string s1, s2;
Assert.IsTrue(s1.Length == 0 && s2.Length == 0);
Assert.IsTrue(!ReferenceEquals(s1, s2));

Оказывается, что большинство. NET Строка API-интерфейсов Framework проверяет пустой результат. Они возвращают string.Empty во всех этих случаях. Например, "x".Remove(0, 1) возвращает string.Empty.

Как я могу создать свободные sh строковые объекты нулевой длины?

Ответы [ 3 ]

8 голосов
/ 13 февраля 2020

Не существует истинного 100% поддерживаемого способа изготовления строки sh нулевой длины. NET. Как подробности реализации , существующие строковые API могут пытаться нормализовать возвращаемые значения нулевой длины для экземпляра string.Empty, но независимо от того, делают ли они это последовательно, не то, на что должен полагаться разработчик.

В частности, у двух других ответов есть проблемы:

  • Решение string.Copy даже включает предупреждение о том, что метод устарел. NET Core 3.0. Вероятно, этот метод будет полностью удален из будущей версии. NET Core, поэтому любое решение, основанное на вызове string.Copy, будет сломано, когда приложение в конечном итоге перейдет на новую версию среды выполнения.

  • Решение FastAllocateString зависит от недокументированного внутреннего API во время выполнения. Внутренние API не гарантированно остаются между версиями. Фактически, мы планируем серьезные изменения в поведении строк в следующей версии. NET, и эта работа почти наверняка повлияет на этот внутренний API.

Итак, на ваш конкретный вопрос о том, существует ли надежный способ изготовления экземпляра строки fre sh нулевой длины, ответ - нет.

Если вы хотите Специальные строки нулевой длины в вашем коде, лучшее решение будет использовать шаблон if (myString.Length == 0) { /* ... */ }. Шаблоны if (myString == string.Empty) { /* ... */ } и if (myString == "") { /* ... */ } также будут работать, но их кодовая строка не будет оптимизирована так же, как первое предложение.

Если вы хотите использовать пустые или пустые строки специального случая, лучшим решением будет использовать существующий string.IsNullOrEmpty API. Реализация этого метода изменяется с версии на версии , чтобы использовать все доступные JIT-оптимизации в данный момент.

Источник: Я один из основных разработчиков в классе System.String.

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

Для этого можно использовать метод FastAllocateString (он используется внутри классов String и StringBuilder). Поскольку он имеет модификатор internal static, вы должны использовать отражение для вызова. Но он возвращает две разные пустые строки в памяти

var fastAllocate = typeof(string).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
    .First(x => x.Name == "FastAllocateString");

string s1 = (string)fastAllocate.Invoke(null, new object[] { 0 });
string s2 = (string)fastAllocate.Invoke(null, new object[] { 0 });
var zeroLength = s1.Length == 0 && s2.Length == 0;
var notEqual = !ReferenceEquals(s1, s2);

Обе проверки возвращают true здесь

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

Вы можете использовать устаревший метод String.Copy

string s1 = "";
string s2 = String.Copy("");
Assert.IsTrue(s1.Length == 0 && s2.Length == 0);
Assert.IsTrue(!ReferenceEquals(s1, s2));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...