C#容器通过引用或值初始化?

时间:2013-02-03 05:01:51

标签: c# reference containers

我对C ++很有经验,但对C#来说有点新鲜。

将容器添加到容器时,是通过引用还是按值传递?

也就是说,如果我这样做:

myClass m = new myClass(0);       //Assume the class just holds an int
List<myClass> myList = new List<myClass>(1);
myList.Add(m);
myList[0] += 1;
Console.WriteLine(m);
Console.WriteLine(myList[0]);

结果是:

0
1

或将是

1
1

如果是前者,那怎么能让我做到后者呢?我的第一直觉是做

之类的事情
myClass ref mref = m; 
Console.WriteLine(mref);

但这似乎不是有效的语法。

1 个答案:

答案 0 :(得分:6)

值通过值传递给Add方法;但是,如果传递引用类型(类始终是引用类型),则值本身是引用。所以问题不在于值是通过值还是通过引用传递,而是类型是值类型还是引用类型。

class MyClass
{
    public int Number { get; set; }
}

通过此声明,我们得到:

MyClass m = new MyClass();
List<MyClass> myList = new List<MyClass>();
myList.Add(m);

myList[0].Number += 1;
Console.WriteLine(myList[0].Number); // Displays 1
Console.WriteLine(m.Number); // Displays 1

myList[0].Number += 1;
Console.WriteLine(myList[0].Number); // Displays 2
Console.WriteLine(m.Number); // Displays 2

请注意,这不适用于struct,因为myList[0]返回的值将是存储在列表中的值的副本。 += 1只会增加此临时副本的Number属性,因此除了消耗几个处理器周期之外没有其他影响。因此,仅创建不可变结构是一个很好的建议。


如果要直接显示对象,请覆盖ToString

class MyClass
{
    public int Number { get; set; }

    public override string ToString()
    {
        return Number.ToString();
    }
}

现在,你可以写

myList[0].Number += 1;
Console.WriteLine(myList[0]);
Console.WriteLine(m);

您甚至可以使myList[0] += 1使用运算符重载。在MyClass声明

public static MyClass operator +(MyClass m, int i) 
{
    m.Number += i;
    return m;
}

但这有点奇怪,除非你的类代表一个数字,但在这种情况下,首选的是struct,因为数字通常被认为是不可变的值类型。

public static MyStruct operator +(MyStruct m, int i) 
{
    return new MyStruct(m.Number + i);
}