Changing size of array in extension method does not work?

守給你的承諾、 提交于 2019-12-01 10:32:04

问题


So basically I wrote my little Add extension method for array types.

using System;
using System.Linq;
public static class Extensions 
{
    public static void Add<T>(this T[] _self, T item)
    {
        _self = _self.Concat(new T[] { item }).ToArray();
    }
}
public class Program
{
    public static void Main()
    {
        string[] test = { "Hello" };
        test = test.Concat(new string[] { "cruel" }).ToArray();
        test.Add("but funny");
        Console.WriteLine(String.Join(" ", test) + " world");
    }
}

The output should be Hello cruel but funny world, but the but funny will never be concatenated within the extension method.

Editing the same array in the extension seems not to work, too:

using System;
using System.Linq;
public static class Extensions 
{
    public static void Add<T>(this T[] _self, T item)
    {
        Array.Resize(ref _self, _self.Length + 1);
        _self[_self.Length - 1] = item;
    }
}
public class Program
{
    public static void Main()
    {
        string[] test = { "Hello" };
        test = test.Concat(new string[] { "cruel" }).ToArray();
        test.Add("but funny");
        Console.WriteLine(String.Join(" ", test) + " world");
    }
}

What did I get wrong here, how can I use it as extension?

.dotNet fiddle: https://dotnetfiddle.net/9os8nY or https://dotnetfiddle.net/oLfwRD

(It would be great to find a way so I can keep the call test.Add("item");)


回答1:


You are assigning a new reference to the argument,it won't change the actual array unless you pass it as ref parameter. Since this is an extension method it's not an option. So consider using a normal method:

public static void Add<T>(ref T[] _self, T item)
{
    _self = _self.Concat(new T[] { item }).ToArray();
}

Add(ref test, "but funny");

Or if you insist on using extension methods you need to make the array second parameter in order to use ref:

public static void AddTo<T>(this T item, ref T[] arr, )
{
    arr = arr.Concat(new T[] { item }).ToArray();
}

"but funny".AddTo(ref test);

Array.Resize doesn't work. Because it changes the _self, not the test array. Now when you pass a reference type without ref keyword, the reference is copied. It's something like this:

string[] arr1 = { "Hello" };
string[] arr2 = arr1;

Now, if you assign a new reference to arr2, it will not change arr1's reference.What Array.Resize is doing is that since resizing an array is not possible, it creates a new array and copies all elements to a new array and it assigns that new reference to the parameter (_self in this case).So it changes the where _self points to but since _self and test are two different references (like arr1 and arr2), changing one of them doesn't affect the other.

On the other hand if you pass array as ref to your method as in my first example, the Array.Resize will also work as expected, because in this case the reference will not be copied:

public static void Add<T>(ref T[] _self, T item)
{
    Array.Resize(ref _self, _self.Length + 1);
    _self[_self.Length - 1] = item;
}



回答2:


I believe the _self = creates a copy of the _self object into the local variable created for the parameter _self - and so the original will not be updated. Use a reference type like a list, or create a static method which returns the new array.

In terms of the 'feel' of the reason: you're calling a method on a variable instance - you can't change that instance from within the code executing under the context of it




回答3:


You may change code like this:

public static class Extensions 
{
    public static T[] Add<T>(this T[] _self, T item)
    {
        return _self.Concat(new T[] { item }).ToArray();
    }
}
public class Program
{
    public static void Main()
    {
        string[] test = { "Hello" };
        test = test.Concat(new string[] { "cruel" }).ToArray();
        test = test.Add("but funny");
        Console.WriteLine(String.Join(" ", test) + " world");
    }
}

As a side note - usage will be same as Concat method.



来源:https://stackoverflow.com/questions/27799341/changing-size-of-array-in-extension-method-does-not-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!