GetItem на TDictionary удален компоновщиком

Я использую TDictionary из <string, string>. Но почему-то компоновщик решает, что я не хочу получать из него элементы.

У меня есть следующий код:

function TSheet.GetFieldName(Field: string; Default: string): string;
begin
  Result := Default;
  if FFieldNames[Field] = '' then
    Result := Field
  else
    Result := FFieldNames[Field];
end;

FFieldNames это TDictionary<string, string>. В строке 2 (if FFieldNames[Field] = '' then) возникает исключение «Файл не найден». Добавление FFieldNames[Field] к моим часам говорит мне, что Вызываемая функция {System.Generics.Collections}TDictionary.GetItem была удалена компоновщиком.

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

Поэтому я создал следующий код:

FFieldNames.Add(Name, S);
V := FFieldNames.Items[Name];

Где S, Name и V — строки. Это из кода, где FFieldNames заполняется данными. Единственная цель V — получить только что вставленный S; больше ничего не делает.

Как ни странно, в то время как отладчик говорит мне то же самое (то есть GetItem исключается), V действительно устанавливается в ожидаемое значение. Но это не в моей функции TSheet.GetFieldName. :|

Что мне не хватает?


person Svip    schedule 08.03.2013    source источник
comment
Я думаю, что ваш код неверен в любом случае. Если ключ отсутствует, то использование Items[] приведет к исключению. Вам нужно TryGetValue. И вам также нужно убедиться, что вы не ищете значение дважды. Вы хотите if not FFieldNames.TryGetValue(Field, Result) then Result := Field; Или, возможно, вы имеете в виду if not FFieldNames.TryGetValue(Field, Result) then Result := Default;. Кроме того, Result := Default бессмысленно, поскольку вы всегда перезаписываете. Компилятор сообщит вам об этом, если вы включите предупреждения.   -  person David Heffernan    schedule 08.03.2013
comment
Эта ошибка возникает только в отладчике, который, похоже, путается с дженериками. Ваша ошибка определенно не вызвана компоновщиком.   -  person jpfollenius    schedule 08.03.2013
comment
Я понял свою ошибку через несколько секунд после того, как опубликовал ее; использование ContainsKey() помогло! Но предложение Хеффернана о TryGetValue тоже хорошая идея. Спасибо за это.   -  person Svip    schedule 08.03.2013
comment
Я неизменно обнаруживаю, что использую только TryGetValue. Возможно, это что-то о диктовках, которые я использую, но я всегда хочу обрабатывать случай, когда ключ не в диктовке, используя логический тест, а не исключение. И я хочу найти значение и проверить ключ в dict за одну операцию для эффективности. Это означает, что я всегда использую только TryGetValue.   -  person David Heffernan    schedule 08.03.2013


Ответы (1)


Та же проблема относится и к TList<>. Даже если в коде используется метод класса, он недоступен из отладчика ("xxx в TList удален компоновщиком"). Я предполагаю, что это проблема с дженериками в целом.

Если вы создадите класс-потомок, у него не будет этой проблемы.

type
  TMyList = class(TList<TMyObject>)

  end;

var
  List : TMyList;
begin
  ...

end;
person AgoraC    schedule 07.09.2017
comment
Хорошая идея, но я попробовал этот подход на TDictionary‹string, TObject›, и это не сработало. Соответствующие методы доступа по-прежнему исключались компоновщиком. - person Josh Doebbert; 23.04.2020