Por que a definição de uma propriedade em um objeto enumerado não trabalho?

StackOverflow https://stackoverflow.com/questions/317527

  •  11-07-2019
  •  | 
  •  

Pergunta

Eu sei muito sobre C #, mas este está me stumping e Google não está ajudando.

Eu tenho uma gama IEnumerable de objetos. Eu quero definir uma propriedade no primeiro. Eu fazê-lo, mas quando eu enumerar sobre a gama de objetos após a modificação, não vejo a minha mudança.

Aqui está um bom exemplo do problema:

    public static void GenericCollectionModifier()
    {
        // 1, 2, 3, 4... 10
        var range = Enumerable.Range(1, 10);

        // Convert range into SubItem classes
        var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i});

        Write(items);  // Expect to output 1,2,3,4,5,6,7,8,9,10

        // Make a change
        items.First().MagicNumber = 42;

        Write(items);  // Expect to output 42,2,3,4,5,6,7,8,9,10
        // Actual output: 1,2,3,4,5,6,7,8,9,10
    }

    public static void Write(IEnumerable<SubItem> items)
    {
        Console.WriteLine(string.Join(", ", items.Select(item => item.MagicNumber.ToString()).ToArray()));
    }

    public class SubItem
    {
       public string Name;
       public int MagicNumber;
    }

O aspecto do C # pára meu "MagicNumber = 42" mudança de ser de saída? Existe uma maneira eu posso obter a minha mudança para "pau" sem fazer algum funk a conversão para List <> ou array?

Obrigado! -Mike

Foi útil?

Solução

Quando você chama First () enumera sobre o resultado deste pedaço de código:

Select(i => new SubItem() {Name = "foo", MagicNumber = i});

Note que o Select é um recenseador preguiçoso, o que significa que ele só faz a escolha quando você pedir um item a partir dele (e fá-lo todas vez que você perguntar isso). Os resultados não são armazenados em qualquer lugar, por isso, quando você chama items.First () você começa uma nova instância SubItem. Quando você, em seguida, passar itens para escrever, ele recebe um monte de novas instâncias SubItem -. Não o que você tem antes

Se você deseja armazenar o resultado de seu seleto e modificá-lo, você precisa fazer algo como:

var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();

Outras dicas

Eu suspeito algo acontecendo em segundo plano. Provavelmente devido ao fato dos IEnumerables só pode ser repetido uma vez.

Será que funciona se você adicionar um 'ToList ()' após a chamada para Select () ao atribuir ao 'itens'?

A única coisa que posso pensar é que items.First () passa uma cópia do SubItem a sua vez da referência, por isso, quando você configurá-lo a mudança não é realizada.

eu tenho que assumir que tem algo a ver com IQueryable apenas ser capaz de ser repetido uma vez. Você pode querer tentar alterar isto:

// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i});

para

// Convert range into SubItem classes
var items = range.Select(i => new SubItem() {Name = "foo", MagicNumber = i}).ToList();

E ver se existem quaisquer resultados diferentes.

Você não pode / não deve modificar uma coleção através de um recenseador. Estou surpreso que isso não lançar uma exceção.

.primeira () é um método, não uma propriedade. Ele retorna uma nova instância do objeto na primeira posição do seu Enumerable.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top