通过引用传递引用类型以指示它将被修改

Pass reference-type by reference to indicate it will be modified

我在我们的应用程序中发现一些代码通过引用传递 List<T> 以表明它已被修改:

void DoSomething(ref List<MyType> theList)
{
    theList.Add(new MyType());
}

我认为在这种情况下 ref 关键字显然已过时,因为我们也可以在没有关键字的情况下向列表中添加新元素。然而,它表明我们修改了列表或至少它的元素。我发现如果您有很多参数并且想查看哪些参数被修改以及哪些只是作为值传递来完成这项工作,我发现这特别有用。

这个问题是否可以肯定是基于意见的,对 SO 来说是无效的,我宁愿问是否有另一种方法来实现这个,或者我是否应该关心它。

编辑:澄清一下我的问题。这个问题不是如果一个列表被修改了,这只是一个例子。或者我也会使用任何其他引用类型,而不仅仅是 List<T>

阅读 interface 比查看 ref 并认为它是可变集合更容易和广泛。

例如,如果你希望它是常量:

public DoSomething<T>(IReadOnlyCollection<T> collection)
{
     //....
}

Non-constant:

public DoSomething<T>(List<T> collection)
{
     //....
}

在值类型的情况下,确实如您在问题中澄清的那样:

常数:

public DoSomething(int value)
{
     //....
}

Non-constant:

public DoSomething(ref int value)
{
     //....
}

或者,如果您的类型无法访问代码,例如 Stream:

public class StreamWrapper
{
    private Stream _instance;

    //now you can specify read or edit methods here and use this class in invokation.
}

However it indicates that we're changing the list.

不,不是。它表示可以更改参考。在我看来,使用 ref 关键字作为 'identifier' 可以改变的东西是不好的,因为它打开了你可能不想要的门。

我建议研究一下 aspect-oriented 编程,您是否可以将属性分配给方法参数。通过新的 Roslyn 编译器及其代码分析服务,您甚至可以检查代码是否违反了给定的原则。

Patrick 引导我找到了一种不依赖属性的替代方法,因此我们可以在 legacy-code 具有较旧编译器的机器上使用它。我们当然可以适当的写API-doc来表示方法修改传入的参数:

/// <summary/>
/// <param name="theList">list to be modified</param>
void DoSomething(List<MyType> theList)

我想这样更好,因为它不依赖于关键字的错误用法。但是,它假设我们 API 的客户仔细阅读了文档。