Alternative to using ref in foreach?

2020-04-05 07:49发布

I have a modifying method with a signature like

private bool Modify(ref MyClass obj);

that will make modifications to obj and indicate succes with it's return value. Modify is not reassigning the reference (I know that this wouldn't work), just modifying instance fields, so I want to use it to do something like the following:

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

I am running into a problem compiling as obj is "not being passed with the ref keyword". However, if I put the ref keyword in like so:

bool success = Modify(ref obj);

I get "cannot use obj as a ref/out because it is a 'foreach iteration variable". I understand that foreach uses an immutable iterator and that's why this doesn't work.

My question is what is the easiest alternative to make something like this work?

I have tried using

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

but they I get "a property or indexer may not be passed as an out of ref parameter".

Thanks your help.

标签: c# foreach ref
3条回答
beautiful°
2楼-- · 2020-04-05 08:28

It is solved by using LINQ.

My Code:

    private static List<string> _test = new List<string>();

    public List<string> Test { get => _test; set => _test = value; }


    static void Main(string[] args)
    {
        string numString = "abcd";

        _test.Add("ABcd");
        _test.Add("bsgd");

        string result = _test.Where(a => a.ToUpper().Equals(numString.ToUpper()) == true).FirstOrDefault();

        Console.WriteLine(result + " linq");
    }
查看更多
手持菜刀,她持情操
3楼-- · 2020-04-05 08:43

You state

Modify is not reassigning the reference

Therefore, there is no reason the Modify(ref MyClass) function needs to pass argument by ref.

You should be able to do the same "modifications", whatever that is (please clarify that) by passing the object reference by value, i.e. removing the ref keyword.

So, the fix here should be changing your Modify function signature from Modify(ref MyClass) to Modify(MyClass)

查看更多
干净又极端
4楼-- · 2020-04-05 08:46

Any type within C# is passed actually by value. When you however pass an instance of a class to a method what is actually passed is not the instance itself but a reference to it which itself is passed by value. So effectivly you're passing instances of a class as reference - which is why you call them reference-types.

This means that you modify the instance referenced by that reference-value in your method, no need to use the ref-keyword.

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

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

If you'd really pass the reference by reference you'd re-assign the obj on every iteration within your loop which isn't allowed within a foreach-block.

On the other side you could also use a classic for-loop. However you'd need a temporary variable to store the outcome of your method:

for(int i = 0; i < myList.Length; i++)
{
    var tmp = myList[i];
    MyMethod(ref tmp);
    myList[i] = tmp;
}
查看更多
登录 后发表回答