Какова цель String.IsInterned? - PullRequest
11 голосов
/ 21 июня 2011

В классе String есть метод IsInterned(). Я никогда не использую этот метод. Пожалуйста, помогите мне понять, как лучше всего использовать этот метод.

Ответы [ 5 ]

9 голосов
/ 24 июня 2015

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

  1. Память не тратится впустую на дублирующиеся строки.
  2. Сравнение равенства между строками, известными как интернируемым, очень быстро.
  3. Сравнение равенства между строками, которые оказались интернированными, все еще намного быстрее, чем если бы они не интернировались.
  4. В некоторых случаях другие сравнения дают выигрыш в производительности.

Он имеетследующие плохие качества:

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

В качестве оптимизации мы используем его там, где либо хорошие качества превосходят плохие, либо плохие.не удерживается (если мы знаем, что строка все равно будет существовать на протяжении всего жизненного цикла приложения, или знаем, что она будет использоваться много раз, то плохая часть не сохраняется).

То же самое мы не используем, когда плохие качества перевешивают хорошие.(Большую часть времени).

IsInterned() можно использовать для нахождения промежуточной точки.

Предположим, у меня есть строковое свойство Name:

public string Name { get; set; }

Допустим, я знаю, что обычно ищут объекты с заданным Name, или пытаются найти объекты с одинаковым Name, или иным образом проводят много сравнений на равенство.ИЛИ Допустим, я знаю, что будет много других объектов с таким же Name.ИЛИ оба.

В этих случаях я мог бы рассмотреть возможность стажировки:

private string _name;
public string Name
{
  get { return _name; }
  set { _name = string.Intern(value); }
}

Конечно, было ли это хорошей идеей или нет, зависит от хороших и плохих качеств интернирования, упомянутых выше.

Между использованием и неиспользованием есть возможность:

private string _name;
public string Name
{
  get { return _name; }
  set { _name = string.IsInterned(value) ?? value; }
}

Здесь, если строка value уже интернирована, то мы с обратной стороны интернирования уже работаем, и мыбольше не страдаем, поэтому мы пользуемся этим.Но если value еще не интернирован, то мы просто используем его как есть.

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

3 голосов
/ 21 июня 2011

Одним из возможных вариантов использования будет блокировка строкового значения.

В следующем:

string s = //get it from somewhere, e.g. a web request
lock (s){
//do something
}

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

Однако есть нечто, называемое intern pool, то есть таблица, которая содержит один экземпляр некоторых строк (например, все литералы есть).

Вы можете использовать его для блокировки работы:

string s = //get it from somewhere, e.g. a web request
lock (string.Intern(s)){
//do something
}

Эта функция возвращает ссылку на строку во внутреннем пуле, которая имеет то же значение, что и s, поэтому безопасна для блокировки.

Функция IsIntern просто проверяет, является ли указанная вами ссылка ссылкой на строку во внутреннем пуле.

2 голосов
/ 21 июня 2011

Обратитесь к сообщению Эрик , я думаю, что это лучшее, где в интернете объясняется

1 голос
/ 21 июня 2011

Строковые литералы в C # интернированы (то есть они хранятся в пуле интернирования), так что для каждого вхождения литерала существует только один экземпляр.Если вы создаете свой собственный язык (например, некоторую систему сценариев), вы можете использовать IsInterned и Intern, чтобы получить то же самое.

0 голосов
/ 21 июня 2011

Посмотрите на это . Там на самом деле есть случай использования в этой теме.

...