在foreach中使用ref的替代方法?

时间:2017-07-28 18:55:37

标签: c# foreach ref

我有一个带有签名的修改方法,如

private bool Modify(ref MyClass obj);

将对obj进行修改,并指出其成功的返回值。 Modify没有重新分配引用(我知道这不会起作用),只是修改实例字段,所以我想用它来做类似以下的事情:

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

我遇到问题正在编译obj是"没有使用ref关键字"传递。但是,如果我将ref关键字放入如下:

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
}

但我得到&#34;属性或索引器可能不会作为ref参数传递#34;。

谢谢你的帮助。

4 个答案:

答案 0 :(得分:13)

C#中的任何类型实际上都是按值传递。然而,当您将类的实例传递给方法时,实际传递的方法不是实例本身,而是引用,它本身通过值传递 / em>的。所以有效你将类的实例作为参考传递 - 这就是你称它们为引用类型的原因。

这意味着您修改方法中该引用值引用的实例,无需使用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;
}

答案 1 :(得分:9)

你陈述

  

修改不会重新分配参考

因此,Modify(ref MyClass)函数没有理由需要通过ref传递参数。

您应该能够通过按值传递对象引用(即删除ref关键字)来执行相同的修改&#34;,无论是什么(请澄清),

因此,此处的修复方法应该是将修改功能签名从Modify(ref MyClass)更改为Modify(MyClass)

答案 2 :(得分:0)

使用LINQ可以解决。

我的代码:

    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 :(得分:0)

使用临时变量绕过消息

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

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