List<T> 或 Collections 的编码风格 "ref"

Coding style "ref" for List<T> or Collections

我有一个函数可以改变列表类型的参数(改变内部对象状态)。例如:

    public void ChangeList<T>(List<T> source, T value)
    {
        //Actions
        source.Add(value);
        //Actions
    }

什么函数签名比较好?为什么?

第一个:public void ChangeList<T>(List<T> source, T value)

第二个:public void ChangeList<T>(ref List<T> source, T value)

编辑:问题可以修改。如何显式指定函数改变列表的状态? (函数名称或 ReadonlyCollection 除外)

第一个。第二个尖叫"I don't know what ref means";这是完全错误的。这甚至不是风格问题,真的。在此上下文中使用 ref 的唯一原因是 ChangeList 方法是否需要 重新分配列表 (返回不同的列表实例,而不是执行名称建议,并改变现有列表)。在那种情况下,我认为 return 会更好:

public List<T> TransformBasedOnList<T>(List<T> source, T value) { ... }

只有在更改列表的引用时才应使用 ref: 例如

public void ChangeList<T>(ref List<T> source, T value)
{
    //Actions
    source = new List<T>; // or initialize using API/DB call
    source.Add(value);
    //Actions
}

扩展我的评论,请参阅此示例应用程序,它展示了通过 ref:

传递参数之间的区别
static void Main(string[] args)
{
    int val = 1;
    int val2 = 1;

    Add(ref val);
    Add(val2);
    Console.WriteLine("Add 44 to Refence of val: " + val);
    Console.WriteLine("Add 44 to i, not by ref:  " + val2);

    Console.ReadKey();
}

static void Add(ref int i)
{
    i += 44;
}

static void Add(int i)
{
    i += 44;
}

输出:

如您所见,当通过 ref 传递值时,您更改了被调用方法范围的值 "outside"。调用方法知道这些更改。基本上,被调用的方法 "has a reference to that variable's memory location" 和那个位置都有一个赋值。我的控制台输出中确实有一个 type-o,应该是 Add 44 to val2, not by ref:

当您使用ref时,更改不会"recognized"超出被调用方法的范围。相反,它传递了参数/参数的 value,忽略了实际的内存引用,仅更改了方法的本地值。

不是一个很好的解释,说实话我的词汇量在这件事上并不出色(如果有人能纠正我,我会很高兴!)但我认为这个例子很简单,屏幕截图清楚地显示了差异.

编辑:另外,只需重新链接 MSDN:

https://msdn.microsoft.com/en-us/library/14akc2c7.aspx

并指出这一重要说明,

Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.

A "reference type" 基本上只是一种仅引用内存位置的类型,因此您可以有 2 个引用相同对象实例的引用类型。 "value type" 直接包含实际值,您不能通过修改不同的值类型来弄乱一个值类型的值;它们是两个不同的实例,恰好具有相同的值。但是,使用 ref,您可以使值类型的行为类似于引用类型。

可以把它想象成 "Get the coat on the third hook"- 这是一个参考。你知道外套在哪里,这是参考。如果你说,"Get my coat" 你就知道你得到的外套(价值)是多少。