Могу ли я использовать элементы StringBuilder в foreach?

Поскольку я использую .NET 1.1, я не могу использовать универсальный список строк, так как дженерики еще не были частью языка. Итак, я пытаюсь использовать StringBuilder, но получаю сообщение об ошибке:

"оператор foreach не может работать с переменными типа "System.Text.StringBuilder", поскольку "System.Text.StringBuilder" не содержит определения для "GetEnumerator" или недоступен"

с этим кодом:

public StringBuilder linesToSend;
. . .

foreach (string _line in this.linesToSend)
{
    serialPort.Write(_line);
}

Что-то не так с моим кодом, или StringBuilder действительно запрещен в циклах foreach? Если последнее, является ли String[] моим лучшим средством?


person B. Clay Shannon    schedule 11.02.2013    source источник
comment
попробуйте использовать List‹string› или ArrayList вместо Clay   -  person MethodMan    schedule 11.02.2013
comment
Примечание. В версии 1.1 вы можете использовать System.Collections. Specialized.StringCollection вместо отсутствующей строки List‹string›.   -  person Anthony Pegram    schedule 11.02.2013
comment
@DJKRAZE: как уже упоминалось, дженерики недоступны в .NET 1.1.   -  person B. Clay Shannon    schedule 11.02.2013
comment
Глина, которую я упомянул или ArrayList тоже..   -  person MethodMan    schedule 11.02.2013


Ответы (6)


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

// Write the complete string to the serialPort
serialPort.Write(linesToSend.ToString());
person Justin Niessner    schedule 11.02.2013

Старый вопрос, я знаю, но что-то потенциально полезное:

Если каждая из ваших строк была построена с помощью .AppendLine или вы вставили новую строку, вы можете сделать

string[] delim = { Environment.NewLine, "\n" }; // "\n" added in case you manually appended a newline
string[] lines = StringBuilder.ToString().Split(delim, StringSplitOptions.None);
foreach(string line in lines){
    // Do something
}
person Jason McKindly    schedule 29.07.2015

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

Если у вас есть переменное количество строк, над которыми вам нужно работать, вы можете использовать ArrayList и перебирать это.

ArrayList strings = new ArrayList();
// populate the list
foreach (string str in strings) {
  // do what you need to.
}

Если вы боитесь, что список массивов может содержать другие объекты (поскольку он не является строго типизированным), вы можете вместо этого безопасно привести его:

foreach (object obj in strings) {
  string str = obj as string;
  // If null strings aren't allowed, you can use the following
  // to skip to the next element.
  if (str == null) {
    continue;
  }
}
person Joshua    schedule 11.02.2013

StringBuilder строит только одну строку, так как же foreach получить целую последовательность строк?

Если вам нужно писать строку за строкой, возможно, используйте ArrayList, добавьте к ней каждую строку строки и foreach с string в качестве типа переменной foreach (Object будет преобразовано в String). Или, что еще лучше, используйте StringCollection (спасибо за комментарий Энтони Пеграма к первоначальному вопросу; я забыл этот класс).

Но почему бы не перейти на более новую версию .NET?

person Jeppe Stig Nielsen    schedule 11.02.2013
comment
Для этого проекта я не могу выполнить обновление. В другом проекте я использую Visual Studio 2010 в Windows 7 и VS 2012 в Windows 8, но этот проект останется в VS 2003/.NET 1.1. - person B. Clay Shannon; 11.02.2013

Цикл foreach работает, вызывая GetEnumerator из интерфейса IEnumerable, который возвращает перечислитель, который foreach использует для получения следующего элемента объекта.

StringBuilder не реализует IEnumerable или IEnumerable<T>, которые позволили бы работать foreach. В этом случае вам лучше использовать string[] или StringCollection, а когда вы закончите, вы можете объединить коллекцию, используя StringBuilder.

ex:

StringBuilder stringBuilder = new StringBuilder();
foreach(string line in array)
{
    serialPort.Write(line);
    stringBuilder.Append(line);
}
person Dustin Kingen    schedule 11.02.2013
comment
Цикл foreach фактически выполняет утиную типизацию своего операнда. Если операнд имеет метод с именем GetEnumerator, тип возвращаемого значения которого включает метод без параметров с именем MoveNext, который возвращает bool, и доступное для чтения свойство с именем Current, которое возвращает тип управляющей переменной, то foreach будет использоваться независимо от того, реализует ли тип IEnumerable или IEnumerable<T> [ если тип явно реализует IEnumerable<T>, но определяет метод GetEnumerator отдельно от интерфейса, цикл foreach будет использовать последний]. - person supercat; 19.02.2013

То, что вы ищете, - это массив строк, если вы знаете количество элементов, или словарь.

person Captain Kenpachi    schedule 11.02.2013
comment
Он изменчив, т.е. вам не нужно заранее указывать количество предметов, которые вы собираетесь в него поместить. Хотя я имел в виду Коллекцию, а не Словарь. Извините. - person Captain Kenpachi; 12.02.2013