2013-11-18 4 views
1

Я пытаюсь создать собственный класс StringBuilder на основе комментариев here.Без мусора Класс String с использованием отражения StringBuilder неправильно инициализируется

Это мой текущий код:

class MyStringBuilder 
{ 
    public StringBuilder stringBuilder; 
    public String linkToStringBuilderString; 

    public MyStringBuilder(int maxCapacity) 
    { 
     stringBuilder = new StringBuilder(maxCapacity, maxCapacity); 

     linkToStringBuilderString = (String)stringBuilder.GetType().GetField("m_StringValue", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(stringBuilder); 
    } 
}; 

Однако последняя строка конструктора, который должен получить постоянную ссылку на внутреннюю строку StringBuilder дает свою нулевую ошибку ссылки компиляции, и я не понимаю, почему.

ответ

4

Давайте сломаем линию, которая не работает.

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

linkToStringBuilderString = (String)stringBuilder.GetType().GetField("m_StringValue", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(stringBuilder); 

Это много чего. Давайте соберем каждую операцию на свою собственную линию:

var type = stringBuilder.GetType(); 
var field = type.GetField("m_StringValue", BindingFlags.NonPublic | BindingFlags.Instance); 
var value = (String)field.GetValue(stringBuilder); 

Теперь Visual Studio должно дать вам более четкое представление о том, что терпит неудачу, когда исключение.

Когда я запускаю этот код, я получаю NullReferenceException на этой линии:

var value = field.GetValue(stringBuilder); 

Это означает, что field равна нулю. Почему это может быть так? Ну, GetField() возвращает null, если запрашиваемое поле фактически не существует. Это происходит, когда вы полагаетесь на внутренние детали реализации классов BCL.

Открытие класса StringBuilder в dotPeek (находится в mscorlib), я не вижу члена с именем m_StringValue. Строка хранится с использованием серии динамически распределенных массивов; он, похоже, не кэшируется в строковой форме.

Глядя на версию 2.0 mscorlib, я вижу, что там используется, чтобы быть полем с этим именем. Поэтому этот класс, по-видимому, был реорганизован, когда появился .NET 4. Опять же, это проблемы с зависимостью от деталей внутренней реализации.

На сайте, которое вы связали, подробно описывается именно эта проблема, есть another article. Надеюсь, этот ответ поможет вам указать себя в правильном направлении в будущем.

Смежные вопросы