2010-07-21 4 views
5
 'Why doesn't this work? 
    Dim myStrings As String() = New String() {string1, string2, string3,} 
    For Each s As String In myStrings 
     If String.IsNullOrEmpty(s) Then 
      s = "" 
     End If 
     s = "-" & s.Trim() & "-" 
    Next 

Если string1 содержит "foo", мое намерение состоит в том, что string1 содержит "-foo-" после цикла выполняется. Как я могу сделать эту работу?Как изменить строки, используя цикл «Для каждого»?

Я предполагаю, что этот код делает копии моих строк и изменяет их. Как я могу изменить свои строки в цикле?

Обновление Я изменил код, чтобы использовать индексы массива:

' It still doesn't work. 
    Dim myStrings As String() = New String() {string1, string2, string3} 
    For i As Integer = 0 To myStrings.Count() - 1 
     If String.IsNullOrEmpty(myStringss(i)) Then 
      myStringss(i) = "" 
     End If 
     myStrings(i) = "-" & myStrings(i) & "-" 
    Next 

Результатом этого кода, в частности, со ссылкой на массив и индекс для каждого элемента, изменяет массив, но мои строки по-прежнему имеют одинаковые старые значения. По-видимому, инициализация массива вроде этого просто копирует мои значения в новый массив. Как изменить исходные значения в цикле?

Акцент: массив предназначен только для циклических целей. Мне нужно изменить string1, string2 и string3 аналогично, но как только этот цикл проходит, для массива больше не нужно. О, и мой реальный код имеет более 3 строк.

Позвольте мне сказать, что если бы я использовал язык с большим количеством указателей и ссылок, я бы просто имел массив указателей, которые указывают на string1, string2, and string3`. Кажется излишним скопировать эти строки в массив.

+1

Если это не будет "Для каждого S As String В myStrings" – Gage

+0

@Gage: Да, это должно быть. Напишите это как ответ, поэтому его можно отметить как правильно =) –

+0

@ Томас, это не ответ, это всего лишь небольшое исправление. – corsiKa

ответ

2

Это не работает, потому что строки являются неизменными в .NET - вы не можете изменить значение string1 без явного задания string1 до некоторого значения, то есть, выполнив:

string1 = "Blah"; 

(Обратите внимание, что вы можете измените значение строкового значения i м в массиве MyString на (например) с использованием for вместо foreach, однако от того, что я понимаю, что это не то, что вы хотите сделать)

чтобы решить проблему, которую вы собираетесь нужно дать лучшую идею o f проблема, которую вы пытаетесь решить, например, вы могли бы избежать необходимости изменять ссылки на строки таким образом, настраивая свой интерфейс (см. this question для вдохновения)

+0

@ Хенк звучит для меня так, как будто они хотят изменить значение 'string1', а не содержимое массива. – Justin

+2

Значение семантики, а не неизменность. –

3

Использовать для/Далее и в конце, myStrings(i) = s, чтобы сохранить результат.

+0

'i' не определен нигде. Ты сделал это, чтобы проверить меня? –

+0

* Причина * Это правильно, так как каждый/дает вам копию каждого элемента. Строки - это объекты, на которые ссылаются объекты, но имеющие семантику значений, поэтому изменения, которые вы делаете ((технически, просто заменяя одно значение другим), принадлежат вашей локальной копии. –

+1

@Rice: 'i' будет индексом для/next loop Хенк относится к. –

1

Итерационные переменные неизменяемы. Либо используйте «классический» цикл или другой массив для хранения ваших строк.

+0

Опять же, не совсем. –

+0

Снова? Если это ссылка на ваш комментарий о том, что строки не являются неизменяемыми, я бы согласился с тем, что здесь не проблема. AFAIK Итерационные переменные (любого типа) доступны только для чтения, и это проблема с приведенным выше кодом. Использование цикла For/Next решит его. – DrunkenBeard

+0

@DrunkenBeard, я отправил некоторый код, используя цикл For/Next, который, похоже, должен решить проблему, но результатом является то, что изменяется только массив. «StringN» по-прежнему остается старым. Можете ли вы предложить что-нибудь? –

1

Это не работает, потому что строки неизменяемы.

Попробуйте это вместо этого.

For x As Integer = 0 To myStrings.Length - 1 
    myStrings(x) = "new string" 
Next 

Редактировать после обновления.

Я не уверен, что это возможно.

Возможно, вы могли бы просто написать функцию?

строка1 = Моя_функция (строка1)

+0

Я не думаю, что это имеет какое-то отношение к неизменности струн. –

+1

Я буду перефразировать: проблема не в том, что строки неизменяемы, это значит, что они имеют семантику значений. '' 'Содержит совершенно хорошую копию значения, и все изменения происходят с' s'. Они просто не имеют никакого отношения к соответствующему элементу в 'myStrings'. –

+0

@ Хенк: Да, код Криса решает проблему. Простите, если я этого не сделаю. –

5

В этом примере в C#, но применяется тот же самый принцип.

string[] myStrings = new string[] { "temp", "temp2", "temp3" }; 
myStrings = myStrings.Select(x => "-" + x + "-").ToArray(); 

Выход:

"-temp-" "-temp2-" "-temp3-"

Ссылка на статью MSDN: http://msdn.microsoft.com/en-us/library/bb548891.aspx

Вы также можете используйте функцию делегата, чтобы проверить, является ли строка пустой. Будет ли работа по обеспечению решения VB и редактировать, когда я получаю это

EDIT:

Dim myStrings As String() = _ 
     {"apple", "banana", "mango", Nothing, "passionfruit", "grape"} 
    myStrings = _ 
     myStrings.Select(Function(fruit) ("-" & fruit & "-")).ToArray() 

Выход:

"-apple-" "-banana-" «-mango- " "-" "-passionfruit-" "-grape-"

EDIT 2: ли элем AME вещь в качестве первого редактирования, но более читаемого

Private Function TESTER(ByVal fruit As String) As String 
    Return "-" & fruit & "-" 
End Function 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)    Handles MyBase.Load 
    Dim myStrings As String() = _ 
     New String() {"apple", "banana", "mango", Nothing, "passionfruit", "grape"} 
    myStrings = _ 
     myStrings.Select(AddressOf TESTER).ToArray() 
End Sub 
+0

Как бы это выглядело, если 'Function (fruit)' было несколько строк кода вместо одной строки? –

+0

@Rice Flour Cookies, это зависит от того, что вы пытаетесь сделать. Я использую функцию делегата, но это только в C#. Я посмотрю на это. Что вы пытаетесь сделать со струнами? – Gage

1

После правки я не думаю, что вы можете сделать это так, как вы хотите. Я думаю, вам лучше копировать свои строки в массив и работать с массивом. Вместо того, чтобы string1, string2, и т.д. ... вы бы массив [0], массив [1], и т.д. ...

Что мешает вам делать это?

+0

Я бы предпочел не писать другую функцию для этого. Я хотел бы, чтобы все функции были в одной функции. Похоже, я могу сделать это с помощью «анонимных делегатов» в .net 4.0 –

2

Учитывая ваше самое последнее обновление, что вы просите не представляется возможным.

Строк следуют семантике значений, так что вы делаете на строку в массиве не имеет никакого влияния на исходной строке. Самое близкое, что вы можете найти в ссылочной строке, - StringBuilder, но это не очень удобно в том, как вы хотите.

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

+0

'string1',' string2' и 'string3' передаются как параметры функции. Я хочу использовать их для разных функций внутри функции, но сначала хочу применить к ним общую операцию. –

+0

Итак, напишите метод «Shared» helper, который берет «строку» по ссылке и вносит изменения. Затем, в верхней части основного метода, просто вызовите помощника один раз для каждого параметра. Я знаю, что нет цикла, но опять же, вы заполняете массив без цикла. –

+0

В ответ на DrunkenBeard вспомогательный метод может быть легко реализован как анонимный делегат * без * закрытия. –

2

В зависимости от характера вашей коллекции, вы можете хранить единство длины массивов в нем, а не строки. Если вы это сделаете, вы сможете изменить 0-й элемент каждого массива, чтобы обновить его.

Например, вы могли бы иметь Dictionary (Of String, String()), который отображается на строки строковых массивов. Если в словаре хранятся массивы с одним элементом, вы можете легко изменить 0-й элемент любого из них, не нарушая словарь. Обратите внимание, что вы не должны делать это со словарем ключами, поскольку словарь не сможет выполнять поиск по содержимому строк.

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

1

Это было бы легко инкапсулируется в ParamArray из ByRef параметров, но это не вариант
:-(

Таким образом, вы, кажется, придется делать это вручную:

Imports System.Runtime.CompilerServices 

Module Module1 

Sub Main() 
    Dim String1 = "foo" 
    Dim String2 = "" 
    Dim String3 As String = Nothing 
    Dim strings() = New StrongBox(Of String)() {New StrongBox(Of String)(String1), New StrongBox(Of String)(String2), New StrongBox(Of String)(String3)} 
    Modify(strings) 
    String1 = strings(0).Value 
    String2 = strings(1).Value 
    String3 = strings(2).Value 
    Console.WriteLine("'{0}' '{1}' '{2}'", String1, String2, If(String3, "NOTHING")) 
    Console.ReadLine() 
End Sub 

Sub Modify(ByVal ParamArray myStrings() As StrongBox(Of String)) 
    For i As Integer = 0 To myStrings.Count() - 1 
     If String.IsNullOrEmpty(myStrings(i).Value) Then 
      myStrings(i).Value = "" 
     End If 
     myStrings(i).Value = "-" & myStrings(i).Value & "-" 
    Next 
End Sub 

End Module 

EDIT : Обратите внимание, что проще сделать что-то вроде этого (он просто ничего не дает, как то, что задает вопрос):

Module Module1 

Sub Main() 
    Dim String1 = "foo" 
    Dim String2 = "" 
    Dim String3 As String = Nothing 
    Modify(String1) 
    Modify(String2) 
    Modify(String3) 
    Console.WriteLine("'{0}' '{1}' '{2}'", String1, String2, If(String3, "NOTHING")) 
    Console.ReadLine() 
End Sub 

Sub Modify(ByRef myString As String) 
    If String.IsNullOrEmpty(myString) Then 
     myString = "" 
    End If 
    myString = "-" & myString & "-" 
End Sub 

End Module 
0

Как было предложено в комментарии @ Justin, альтернативой является использование синтаксиса Dictionary и VB With и !.

Module Module1 

Sub Main() 
    Dim strings As New Dictionary(Of String, String) 
    With strings 
     !String1 = "foo" 
     !String2 = "" 
     !String3 = Nothing 
     Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING")) 
     Modify(strings) 
     Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING")) 
     ModifySome(strings, "String1", "String2") 
     Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING")) 
    End With 
    Console.ReadLine() 
End Sub 

Sub Modify(ByVal myStrings As Dictionary(Of String, String)) 
    ModifySome(myStrings, myStrings.Keys.ToArray) 
End Sub 

Sub ModifySome(ByVal myStrings As Dictionary(Of String, String), ByVal ParamArray someStrings() As String) 
    For Each s As String In someStrings 
     If String.IsNullOrEmpty(myStrings(s)) Then 
      myStrings(s) = "" 
     End If 
     myStrings(s) = "-" & myStrings(s) & "-" 
    Next 
End Sub 

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