为什么一个扩展会发生变异而另一个不会

Why does one extension mutate but the other doesn't

我在玩 C# 扩展,对 mutate 方法感到困惑。

下面是两个应该更改调用列表的代码示例。第一个 (shuffle) 有效,但第二个 (CustomExtension) 保持列表不变。

在 CustomExtension 调用结束时,列表参数看起来已更改,但从该方法返回时,列表看起来未受影响。

为什么一个有效而另一个无效?怎么回事?

有效。

readonly private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{

    int n = list.Count;
    while (n < 1)
    {
        n--;
        int k = rng.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}
myList.Shuffle();

(以上内容摘自Randomize a List<T>

这不是

static void CustomExtension(this IList<int> list)
{
    list = new List<int>() { 9, 10, 11 };
}
foo.CustomExtension();

在第一个示例中,您将覆盖 List<T> 中的元素。这会就地改变列表。

在第二个示例中,您正在创建一个新列表并替换 本地引用 list,这是一个 not 使用 ref 传递,因此它在方法范围之外没有影响。您的 foo 实例未在 CustomExtension.

中发生突变

C# 中的扩展方法无法使用 ref 传递 this 参数,因此您无法覆盖调用方的实例引用。

如果您将方法和调用站点更改为带有 ref 参数的普通方法,那么它会按预期工作(但它仍然没有变异 foo,它正在替换它) :

static void CustomExtension(ref IList<int> list)
{
    list = new List<int>() { 9, 10, 11 };
}

CustomExtension( ref foo );