How can i assign a value to a char variable in a foreach loop? C#

Viewed 295

I am trying to do is something like this:

StringBuilder sb = new StringBuilder();

foreach(char ch in valor)
{
    if (ch == ',')
        ch = '.';
    else if (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9' || ch == ',')
    {
        sb.Append(ch);
    }
}

What I want is, if the character is a comma, to make it a dot. But i get the following error

it is not possible to assign value to 'ch' because it is a foreach interaction variable

4 Answers

Why not append in both if branches?

foreach(char ch in valor)
{
    if (ch == ',')
    {
        sb.Append('.');
    }
    else if (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9')
    {
        sb.Append(ch);
    }
}

Just introduce a local variable

StringBuilder sb = new StringBuilder();

foreach(char ch in valor)
{
    var tmp = ch == ',' ? '.' : ch;

    if (char.IsDigit(tmp) || tmp == '.')
    {
        sb.Append(tmp);
    }
}

You can also use the static char.IsDigit() method to check whether a char is a digit or not

You could also do it only with linq:

var sb = new StringBuilder();
sb = valor
    .Select(c => c == ',' ? '.' : c)
    .Where(c => char.IsDigit(c) || c == '.')
    .Aggregate(sb, (sb, c) => sb.Append(c));

Short answer: it is impossible.

Using an immutable foreach indexed item you need to use an intermediate variable like that:

foreach ( char ch in valor )
{
  char c = ch;
  if ( c == ',' )
  {
    c = '.';
  }
  if ( c == '0' || c == '1' || c == '2' || c == '3' || c == '4'
    || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'
    || c == '.' )
  {
    sb.Append(c);
  }
}

I removed the else because it seems to be a mistake...

But in this case you may prefer directly use a for to avoid this useless intermediate variable and so to optimize speed and memory:

for (int index = 0; index < valor.Length; index++)
{
  char c = valor[index];
  if ( c == ',' )
  {
    c = '.';
  }
  if ( c == '0' || c == '1' || c == '2' || c == '3' || c == '4'
    || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'
    || c == '.' )
  {
    sb.Append(c);
  }
}

Next, in the case of the code provided, we can refactor like that, using the else in the right way now:

for (int index = 0; index < valor.Length; index++)
{
  char c = valor[index];
  if ( c == ',' )
  {
    sb.Append('.');
  }
  else
  if ( c == '0' || c == '1' || c == '2' || c == '3' || c == '4'
    || c == '5' || c == '6' || c == '7' || c == '8' || c == '9' )
  {
    sb.Append(c);
  }
}

Also, in the case of the code provided, we can improve to this:

for ( int index = 0; index < valor.Length; index++ )
{
  char c = valor[index];
  if ( c == ',' )
  {
    sb.Append('.');
  }
  else
  if ( char.IsDigit(c) )     // or IsNumber
  {
    sb.Append(c);
  }
}

And to optimize better:

for ( int index = 0; index < valor.Length; index++ )
{
  char c = valor[index];
  if ( c == ',' )
  {
    sb.Append('.');
  }
  else
  if ( c >= '0' && c <= '9' )
  {
    sb.Append(c);
  }
}

So using a foreach we can write, but a little less optimized while being more clean:

foreach (char ch in valor )
{
  if ( ch == ',' )
  {
    sb.Append('.');
  }
  else
  if ( ch >= '0' && ch <= '9' )
  {
    sb.Append(ch);
  }
}

Char.IsDigit Method

Char.IsNumber Method

foreach, in (C# reference)

for (C# reference)

You can try this:


StringBuilder sb = new StringBuilder();
var valor = "google,com1234";

if (valor.Contains(','))
{
   valor = valor.Replace(",", ".");
}
foreach (char ch in valor)
{
   if (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9' || ch == '.')
    {
        sb.Append(ch);
    }
}
Related