Вы также можете преобразовать строку в массив символов следующим образом:
let text = "My Text"
let index = 2
let charSequence = text.unicodeScalars.map{ Character([110]) }
let char = charSequence[index]
Это способ получить символ по указанному индексу в постоянное время.
Пример ниже не работает в постоянное время, но требует линейного времени. Так что если у вас есть много поиска в строке по индексу, используйте метод выше.
let char = text[text.startIndex.advancedBy(index)]
Не существует такой конструкции для обновления цикла; итератор доступен только для чтения. Например, следующий пример представляет собой вполне допустимый итератор:
public IEnumerable<int> Get1Thru5() {
yield return 1; yield return 2; yield return 3;
yield return 4; yield return 5;
}
Как он будет обновляться? Что он будет обновлять?
Если данные представляют собой массив / список / и т. Д., То что-то вроде:
for(int i = 0 ; i < arr.Length ; i++) {
arr[i] = "new value";
}
Или другие параметры в зависимости от конкретного контейнера.
Обновить; на push , метод расширения:
public static void UpdateAll<T>(this IList<T> list, Func<T, T> operation) {
for (int i = 0; i < list.Count; i++) {
list[i] = operation(list[i]);
}
}
static void Main() {
string[] arr = { "abc", "def", "ghi" };
arr.UpdateAll(s => "new value");
foreach (string s in arr) Console.WriteLine(s);
}
No. Оператор foreach
- это просто синтаксический сахар поверх интерфейса IEnumerable
. Этот интерфейс определяет метод получения en IEnumerator
, который, в свою очередь, имеет методы для перечисления только для чтения :
foreach(string s in strings)
{
Console.WriteLine(s);
}
- это ярлык компилятора для:
IEnumerator e = strings.GetEnumerator();
string s;
while(e.MoveNext())
{
s = e.Current;
Console.WriteLine(s);
}
Поскольку IEnumerator.Current является свойством только для получения, вы не можете установить значение.
// Non-generic IEnumerator shown.
interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
Если вы хотите поддерживать обновляемый перечислитель вам нужно будет создать его самостоятельно, но вы не сможете использовать с ним «foreach», и вам придется реализовать оболочки для всех распространенных классов IEnumerable.
Вам придется проанализировать текущие ситуация и придумать как обновить. Если вы используете интерфейс IList, вы можете:
for(int i = 0; i < strings.Count; ++i)
{
string s = strings[i];
//do work
s = s.ToUpperInvariant();
strings[i] = s;
}
В случае строки, нет; C # строки неизменяемы (не могут быть изменено). Если бы вы перечисляли объекты другого изменяемого типа, вы можете изменить свойства этих
Просто чтобы проиллюстрировать, о чем говорит Иаков. Рассмотрим фрагмент кода ниже:
class MyInt
{
public int Val { get; set; }
public MyInt(int val) { this.Val = val; }
}
class Program
{
static void Main(string[] args)
{
MyInt[] array = new MyInt[] { new MyInt(1), new MyInt(2) };
foreach (var obj in array) Console.Write("{0}\t", obj.Val);
foreach (var obj in array)
{
obj = new MyInt(100); // This doesn't compile! the reference is read only
obj.Val *= 10; // This works just fine!
}
foreach (var obj in array) Console.Write("{0}\t", obj.Val);
}
}
В самом деле, если вы попытаетесь назначить объекту, как указано выше, вы получите ошибку времени компиляции. Но ничто не мешает вам изменить свойства MyInt через ссылку "obj"
В случае строки - нет; Строки C # неизменяемы (не могут быть изменены). Если вы выполняли перечисление объектов другого изменяемого типа, вы можете изменить свойства этих объектов.