Error del compilador CS1656

Actualización: noviembre 2007

Mensaje de error

No se puede asignar a 'variable' porque es 'tipo de variable de sólo lectura'
Cannot assign to 'variable' because it is a 'read-only variable type'

Este error aparece cuando se produce una asignación a una variable en un contexto de sólo lectura. Entre los contextos de sólo lectura se incluyen las variables de iteración foreach, las variables using y las variables fixed. Para resolver este error, evite las asignaciones a una variable de instrucción en bloques using, instrucciones foreach e instrucciones fixed.

Ejemplo

El ejemplo siguiente genera un error CS1656 porque intenta reemplazar elementos completos de una colección dentro de un bucle foreach. Una forma de impedir que se produzca este error es cambiar el bucle foreach por un bucle for. Otra forma de hacerlo que se no se muestra aquí consiste en modificar los miembros del elemento existente; esto es posible con las clases, pero no con las estructuras.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace CS1654_2
{

    class Book
    {
        public string Title;
        public string Author;
        public double Price;
        public Book(string t, string a, double p)
        {
            Title=t;
            Author=a;
            Price=p;

        }
    }

    class Program
    {
        private List<Book> list;
        static void Main(string[] args)
        {
            Program prog = new Program();
            prog.list = new List<Book>();
            prog.list.Add(new Book ("The C# Programming Language",
                                    "Hejlsberg, Wiltamuth, Golde",
                                     29.95));
            prog.list.Add(new Book ("The C++ Programming Language",
                                    "Stroustrup",
                                     29.95));
            prog.list.Add(new Book ("The C Programming Language",
                                    "Kernighan, Ritchie",
                                    29.95));
            foreach(Book b in prog.list)
            {
                // Cannot modify an entire element in a foreach loop 
                // even with reference types.
                // Use a for or while loop instead
                if(b.Title == "The C Programming Language")
                    b = new Book("Programming Windows, 5th Ed.", "Petzold", 29.95); //CS1654
            }

            //With a for loop you can modify elements
            //for(int x = 0; x < prog.list.Count; x++)
            //{
            //    if(prog.list[x].Title== "The C Programming Language")
            //        prog.list[x] = new Book("Programming Windows, 5th Ed.", "Petzold", 29.95);
            //}
            //foreach(Book b in prog.list)
            //    Console.WriteLine(b.Title);

        }
    }
}

El ejemplo siguiente muestra cómo puede generarse CS1656 en otros contextos además de un bucle foreach:

// CS1656.cs
// compile with: /unsafe
using System;

class C : IDisposable
{
    public void Dispose() { }
}

class CMain
{
    unsafe public static void Main()
    {
        using (C c = new C())
        {
            c = new C(); // CS1656
        }

        int[] ary = new int[] { 1, 2, 3, 4 };
        fixed (int* p = ary)
        {
            p = null; // CS1656
        }
    }
}