Альтернатива использованию ref в foreach?

у меня есть метод изменения с подписью, такой как

private bool Modify(ref MyClass obj);

это внесет изменения в obj и укажите succes с его возвращаемым значением. Modify не переназначает ссылку (я знаю, что это не сработает), просто изменяя поля экземпляра, поэтому я хочу использовать ее для чего-то вроде следующего:

foreach(MyClass obj in myList)
{
    bool success = Modify(obj);
    // do things depending on success
}

я сталкиваюсь с проблемой компиляции как obj это "не передается с ref ключевое слово". Однако, если я поставлю ref ключевое слово в like so:

bool success = Modify(ref obj);

Я получаю "не удается использовать obj как ref/out потому что это переменная итерации foreach". Я понимаю, что foreach использует неизменяемый итератор, и поэтому это не работает.

мой вопрос в том, какая самая простая альтернатива сделать что-то вроде этой работы?

Я пробовал использовать

foreach(int i = 0; i < myList.Count; i++)
{
    bool success = Modify(ref myList[i]);
    // do things depending on success
}

но они я получаю " свойство или индексатор не могут быть переданы как из ref параметр."

Спасибо за помощь.

2 ответов


вы в состоянии

изменить не переназначает ссылку

следовательно, нет причин Modify(ref MyClass) функция должна передать аргумент ref.

вы должны иметь возможность делать те же самые" модификации", что бы это ни было (пожалуйста, уточните это), передавая ссылку на объект по значению, т. е. удаляя ref ключевое слово.

Итак, исправление здесь должно изменить вашу подпись функции Modify от Modify(ref MyClass) to Modify(MyClass)


любой тип в C# фактически сдал по стоимости. Однако, когда вы передаете экземпляр класса методу, что такое на самом деле передан не сам экземпляр, а ссылка ему, который сам передается по стоимости. Так что эффективно вы передаете экземпляры класса в качестве ссылки - вот почему вы называете их ссылочными типами.

Это означает, что вы изменить экземпляр, на который ссылается это ссылочное значение в вашем методе, не нужно использовать ref-ключевое слово.

foreach(var m in myList)
{
    MyMethod(m);
}

MyMethod(MyClass instance)
{
    instance.MyProperty = ...
}

если вы действительно передадите ссылку по ссылке вы бы повторно назначить obj на каждой итерации в цикле, который не допускается в течение foreach-блок.

С другой стороны, вы также можете использовать классический цикл for. Однако вам понадобится временная переменная для хранения результата метода:

for(int i = 0; i < myList.Length; i++)
{
    var tmp = myList[i];
    MyMethod(ref tmp);
    myList[i] = tmp;
}