Как изменить поле в коллекции объектов, которые я передаю - PullRequest
3 голосов
/ 27 октября 2011

Я пытаюсь сделать следующее ... (Foo - это класс)

void Main() 
{
    var foos = ...
    DoSomeWork(foos);
    // I want all foos to have Bar set to 42
}

public static void DoSomeWork(IEnumberable<Foo> foos) 
{
    foreach (var foo in foos)
    {
        foo.Bar = 42;
    }
}

class Foo 
{
    String blahblah;
    Int32 Bar;
}

Но все foos имеют свои первоначальные значения.Как мне изменить их по параметру ref?

Ответы [ 3 ]

3 голосов
/ 27 октября 2011

Поскольку вы не принудительно выполняете запрос LINQ с помощью таких методов, как ToList или ToArray, каждый раз, когда вы перечисляете запрос, он выполняется заново.Вам необходимо кэшировать результаты запроса с помощью метода ToList, а затем передать этот список методу DoSomeWork.

2 голосов
/ 27 октября 2011

Может быть, foos является генератором IEnumerable.Пример:

IEnumerable<Foo> GetFoos()
{
  yield return new Foo {};
  yield return new Foo {};
  yield return new Foo {};
}

var foos = GetFoos();

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

Теперь, если вы сделали следующее, как предложено@YuriyRozhovetskiy, это будет работать.

var foos = GetFoos().ToList();

Теперь мы можем счастливо мутировать:)

0 голосов
/ 27 октября 2011

Это странно, оно должно работать для ссылочного типа (класса) и не будет компилироваться для типа значения (struct).

Прежде всего, вам не нужно передавать ref IEnumerable в DoSomeWork,потому что вы не хотите изменять объект коллекции, изменяйте только элементы внутри.

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

  • Какую коллекцию вы передаете (List, Set)?
  • Если Bar является свойством - как оно реализовано?
  • Является ли Fooтип ссылки (класс)?

Рабочий код:

class Foo
{
    public Foo(int bar, int baz)
    {
        Bar = bar;
        Baz = baz;
    }
    public int Bar { get; set; }
    public int Baz;
}

class Program
{
    static void Main(string[] args)
    {
        var foos = new List<Foo>(new[]
        {
            new Foo(1, 2),
            new Foo(3, 4),
            new Foo(5, 6)
        });
        DoSomeWork(foos);
    }

    private static void DoSomeWork(IEnumerable<Foo> foos)
    {
        foreach (var foo in foos)
        {
            foo.Bar = 42;
            foo.Baz = 42;
        }
    }
}
...